2018.7.30
前文:回溯法和dfs是不一样的,回溯法有自己很独特的模板,dfs是一种思想,回溯法是dfs的一种实现。
先来看回溯法的典型题型:
Find a path to success 有没有解
Find all paths to success 求所有解
1.求所有解的个数 2. 求所有解的具体信息
Find the best path to success 求最优解
对应的三种模板:
第一种,返回值是true/false。
第二种,求个数,设全局counter,返回值是void;求所有解信息,设result,返回值void。
第三种,设个全局变量best,返回值是void。
一般情况下,第二种居多,第二种也是最难理解了,得到了所有可行的解,自然可以得出这些解中的最优解。
下面给出第二种的常见题型和解答:
77. Combinations https://leetcode.com/problems/combinations/description/
Combination Sum https://leetcode.com/problems/combination-sum/description/
Subsets : https://leetcode.com/problems/subsets/
Subsets II (contains duplicates) : https://leetcode.com/problems/subsets-ii/
Permutations : https://leetcode.com/problems/permutations/
总结上述的这些题型就有一个特点,找出满足给定条件的集合,实际就是满足条件的结果树,进行回溯法遍历即可。
如果题目说,给定一个集合,然后给某种条件,去找到满足条件的所有结果,这一类都可以用回溯法来完成。
这一类的经典模板如下:
ans用来保存中间结果,这里需要说明的是ans是拷贝赋值,也就是说叶子节点的深搜不影响到父节点,所以父节点只需要将当前节点插入的数据弹出即可,那么遍历下一个情况的时候,ans就是空的了,相当于当前节点弹出,进行到下一个节点了。
注意点:
start,遍历的起始位置
ans,中间结果的保存
pop_back,回溯到上一层
那么这种回溯的模板和dfs有什么区别呢?
dfs可以简单理解为中序遍历,其实是一种遍历的方法,它保留了所有的节点信息,例如遍历到叶子节点,然后递归回来,继续遍历右子数,再去递归到叶子节点,每个节点的数据都保存了一遍。
而对于回溯,和dfs不同的是,它往往使用的是循环,循环遍历结果的初始可能性。
两者区别也不是那么大,只是某一类情况,用回溯更加清楚直接。