总结:
所有的Deque 类型或者 LinkedList类型的变量 统计长度都是使用 path.size() 来实现的
递归中到下一层 位置变更为 i + 1,而不是 begin + 1
如果出现给定的数组是重复的情况,则首先要进行排序,然后执行去重
组合问题和子集问题需要设置begin位置,而排列问题不需要设置begin 位置
组合问题
- 对于组合问题,关键要注意的是,若是要求不重复,则在回溯中的下一个位置是 i + 1 ,注意超过范围则剪枝
- 还有就是若给定的数组中包含重复的元素 需要进行去重 而且需要排序 如下
if(i > begin && candidates[i] == candidates[i - 1]) continue;
对于组合问题:组合总和中需要排序、组合总和II 也需要排序、
子集问题
- 关键是在回溯的一开始位置就将path 加入到res 中
- 若有重复元素执行去重 if(i > begin && nums[i] == nums[i - 1]) continue 还需要排序
排列问题
- 排列问题需要设置used 数组,记录之前是否使用过某位置的元素
- 对于普通的排列问题,当 if(used[i]) 则 continue
- 对于有重复元素的排列问题, if(i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) continue 即检测上一个位置是否已经被释放,只有当 if(used[i] == false) 即当前位置为false 的时候,才执行递归操作
对于path 的类型初始化
初始化的方式 如下 都是可以的,但是要注意在定义的recur 函数中,也要注意一致化的问题
- LinkedList< Integer> path = new LinkedList<>();
- Deque< Integer> path = new LinkedList<>();
组合
普通组合问题
- 这种类型是最基础的类型,在回溯的终止条件中,值需要判断path 的 size 是否和 k 相等即可,相等则使用res 保存当前的 path。
- 在递归过程中 ,递归之前加入 ,递归之后撤销
对于计算总和的题目,若给定了数组则都要进行排序
组合总和I
- 此时需要计算组合的sum 为 target的情况
- 只有当sum == target 的时候,才保存当前的path
- for 循环中,先判断sum 是否 是 大于 target ,若是,则break
- 递归之前 sum += candidates[i] 然后path 添加,递归之后 撤销上述两项
组合总和II
- 要求每个数组中的值 ,只能使用一次
- 也是先排序,然后此题没有定义sum,于是采用的是target 自动减去值得方式,最后的截止条件是,当target == 0 的时候,使用res 来保存当前的path
- 在for 循环中,需要进行 判断当前的 元素是否和上一个元素相等的操作 (去重)
组合总和III
- 此题没有给定数组,将数字限定1-9 而且不能重复使用
- 要求 实现 k 个数字的和 为 n## 标题
- 因此截止条件不仅要写sum == n 还要满足path.size() == k
- for 循环的递归之前也是两步,先计算sum ,再计算 path ,递归之后撤销
- 因为是不重复使用,则递归时,每次开始的位置 是 i + 1
子集
子集I
- 满足不重复,而且不限制和为多少,只是统计有多少个子集
- 进入回溯函数的时候,先使用res 来 保存path
- 截止:当子集的长度越界的时候,即子集的开始位置 和数组长度相等的时候
- for循环和之前类似
子集II
- 次问题和子集I 的不同处是,此时给定的数组内有重复元素,但是要求结果不能包含重复的子集
- 当遇到出现重复元素,但是要满足结果不包含重复元素的问题,关键位置是进行排序
- 在for 循环中,需要执行判断 nums[i] == nums[i - 1]
排列
全排列I
- 给定的数组是不包含重复元素的,要求返回所有的排列
- 这种排列问题要设置used 数组,来判断当前元素是否被使用过
- 如果被使用过,则直接continue,
若没有则先used[i] =true; 以及 path.addLast(nums[i]);
之后执行撤销
全排列II
- 此题与上一题的不同是:给定的数组内包含了重复元素,但是要求返回不重复的排列
- 对于这种问题,也是要先排序
- 也是要使用used数组,但是要添加上出重处理
- 在for 内 nums[i] == nums[i - 1] && used[i - 1] == false 时说明上一个位置已经被使用过,因为其used 值为FALSE(被释放了)则continue
- 只有当 当前元素的used 为FALSE的时候,才执行 path 添加和used修改的操作