目录
- 参考
- 算法模板
- 注意事项
- 相关题目
- [46. 全排列](https://leetcode-cn.com/problems/permutations/)
- [47. 全排列 II](https://leetcode-cn.com/problems/permutations-ii/)
- [78. 子集](https://leetcode-cn.com/problems/subsets/)
- [90. 子集 II](https://leetcode-cn.com/problems/subsets-ii/)
- [77. 组合](https://leetcode-cn.com/problems/combinations/)
- [39. 组合总和](https://leetcode-cn.com/problems/combination-sum/)
- 40. 组合总和II
- [437. 路径总和 III](https://leetcode-cn.com/problems/path-sum-iii/)
参考
算法模板
回溯法的本质是,多叉树的深度优先搜索。
来自参考博文3:
result = []
def backtrack(路径, 选择列表):
if 满足结束条件:
result.add(路径)
return
for 选择 in 选择列表:
做选择
backtrack(路径, 选择列表)
撤销选择
撤销选择是为了维护正确的路径。回溯法用的是深度优先搜索,到达叶子结点后需要向后退遍历其它结点,退的时候就需要先撤销当前选择,才能进行新的选择,否则会出现混乱。
注意事项
- 流程?先把迭代的大框架写好,然后补充stop、cut等细节。
- 三要素?dfs形参、迭代逻辑、结束条件。
要素 | 回溯法 | 动态规划 |
---|---|---|
状态 | dfs形参 | dp状态定义 |
方程 | 递归逻辑 | 状态转移方程 |
边界 | 结束条件 | 边界条件 |
优化 | 剪枝、备忘录 | 状态压缩 |
- 递归函数dfs需要哪些形参?需要模拟迭代过程来确定,包含当前结点、路径、结果集合、其它需要在迭代中传递的参数。如果形参个数太多,可把少量相对固定、与迭代过程关联小的变量,放到成员变量中。例如下面的代码中,begin为结点信息,path为路径,res为结果集。哪些变量可以放到成员变量中呢?len、res、candidates比较适合放到成员变量中,而begin、target、path与迭代密切相关,应该始终放到形参中。
/**
* @param candidates 候选数组
* @param begin 搜索起点
* @param len 冗余变量,是 candidates 里的属性,可以不传
* @param target 每减去一个元素,目标值变小
* @param path 从根结点到叶子结点的路径,是一个栈
* @param res 结果集列表
*/
private void dfs(int[] candidates, int begin, int len, int target, Deque<Integer> path, List<List<Integer>> res) {}
- 排列、子集、组合的区别?
题型 | 区别 |
---|---|
排列 | 有顺序,[1,2]和[2,1]是不同的排列。排列长度都是n。 |
子集 | 无顺序,[1,2]和[2,1]是重复的子集。子集长度可以从0~n,0为空集。 |
组合 | 每个元素可能取1次,也可能取多次。 |
- 元素是否能多次使用?如果每个数能使用多次,则下层迭代的起始位置是当前数。如果每个数只能使用一次,则下层迭代的起始位置是下一个数。例如选择列表为[1,2,3],本层选2, 如果能使用多次,则下层选择列表为[2,3];如果只能使用一次,则下层选择列表为[3]。
- 相同元素去重?首先要对原数组排序,然后同一层不能选择重复的数。例如选择列表为[1,2,3,1], 先排序变成[1,1’,2,3],同一层不能取重复的数,本层先选1,跳过1’,再选2,再选3。
相关题目
46. 全排列
47. 全排列 II
- 和46相比需要去重。例如排列[1,1’,2]和[1’,1,2]重复,[1’,1,2]需要剪枝,同一层不能取重复的数。假如选择列表为[1,1’,2],本层先选择1,本层下一个选择需要跳过相同的数1’选2。
78. 子集
- [1,2]和[2,1]是不同的排列,却是相同的子集。如果选择列表为[1,2,3],本层选2时,下一层选择列表为[3],这样才能去掉重复的子集。
90. 子集 II
- 和78相比需要去重。例如子集[1,1’,2]和[1’,1,2]重复,同一层不能取重复的数。
77. 组合
39. 组合总和
- 和40相比,这里每个数能使用多次,所以下一层迭代的起始位置是当前数。例如选择列表为[1,2,3],本层选2, 因为一个数可以用多次,所以下一层选择列表是[2,3]。
40. 组合总和II
- 40. 组合总和II
- 和39相比,这里每个数只能使用一次,所以下一层迭代的起始位置是下一个数。例如选择列表为[1,2,3],本层选2,因为一个数只能用1次,所以下一层选择列表为[3]。
- 需要去重。选择列表中有重复的数,例如选择列表为[1,1’,2,3],同一层不能取重复的数,本层先选1,1’需要跳过,再选2,再选3。
437. 路径总和 III
- 和其他回溯有点不一样?