前言
最近在leetcode刷题,对于平常不是很清楚的一些数据结构和算法重新回顾和巩固一遍
目的
了解回溯和递归的区别,另外弄清楚回溯的特点和应用场景
正文
回溯和递归的区别和联系
1 | 递归:递归是一种算法结构,函数调用本身,最直接的递归应用就是计算连续数的阶乘,计算规律:n!=(n-1)!*n,还有汉诺塔的实现 |
两者之间的联系:回溯多用递归实现
回溯的特点
1 | 搜索策略:符合递归算法,问题解决可以化为子问题,算法类似,规模减小; |
选择回溯的前提
1 | 选择:对于每个特定的解,肯定是由一步步构建而来的,而每一步怎么构建,肯定都是有限个选择,要怎么选择,这个要知道;同时,在编程时候要定下,优先或合法的每一步选择的顺序,一般是通过多个if或者for循环来排列 |
回溯参数的设计
1 | 必须要有一个临时变量(可以就直接传递一个字面量或者常量进去)传递不完整的解,因为每一步选择后,暂时还没构成完整的解,这个时候这个选择的不完整解,也要想办法传递给递归函数。也就是,把每次递归的不同情况传递给递归调用的函数。 |
扩展
#784 LetterCasePermutation1 | /** |
思路根据上面的对于回溯的理解设计参数,我们从最简单的情景来设计程序,假设串是a,那么结果就是a,A,那么这个最简单的逻辑是什么了?先把当前串写入集合中,把第i个字母大小转换(数字不管)就是下面这段,要注意的是:要保证递归函数返回后,状态可以恢复到递归前,以此达到真正回溯,因此注释的那段很重要,要加上,否则回溯会有问题
1 | public class LetterCasePermutation784 { |
运行结果截图
运行流程分析
Runtime: 10 ms, faster than 45.47% of Java online submissions for Letter Case Permutation.
#401 BinaryWatch(二进制手表)1 | /** |
这里拿到题目之后,感觉可以用回溯发,开始设计回溯参数
1.最开始的时候没有设计最后一个参数,for循环中i=0而不是index,这样导致选了之后在选,重复了,这里我们没有恢复状态,因为我们也没有改变状态,我们只是遍历取合适的值
2.另外一个小问题是组合的时候需要清空列表
Runtime: 3 ms, faster than 56.44% of Java online submissions for Binary Watch.
其他需要回溯方法解决的leetcode题目:https://leetcode.com/tag/backtracking/
参考资料
1.https://www.jianshu.com/p/4c5ccac18fac 递归2-回溯与递归 偏偏注定要落脚丶
2.https://blog.csdn.net/u014772862/article/details/51789015 回溯和递归区别 繁拾简忆
3.https://blog.csdn.net/sinat_27908213/article/details/80599460 回溯算法超通俗易懂详尽分析和例题 littlelufisher