http://www.imooc.com/article/39641
重新梳理一遍:
如果一个题目给你几个数组,要求得到他们的组合、子集、或是排列
,那么这时候可以考虑使用回溯法。
回溯法套路:
- 一个返回结果变量res,一个临时变量或者叫路径变量temp
- 对于不要求重复的可能需要排序,需要
i > 0 && nums[i] == nums[i - 1]
这样的操作剪枝 - 往全局变量中添加临时变量时,如果临时变量是引用类型,要注意建立一个新的对象,不然后续值可能会改变。
res.add(new ArrayList<>(temp));
例子
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次
。
说明:
所有数字(包括目标数)都是正整数
。
解集不能包含重复的组合
。
示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
public static List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<>();
if (candidates == null) {
return res;
}
List<Integer> temp = new ArrayList<>();
Arrays.sort(candidates);
traceBack(res, temp, candidates, target, 0, 0);
return res;
}
//98,94
public static void traceBack2(List<List<Integer>> res, List<Integer> temp, int[] candidates, int target, int sum, int start) {
if (sum == target) {
res.add(new ArrayList<>(temp));
return;
}
//int i=start ,表示只能使用一次。
for (int i = start; i < candidates.length; i++) {
//改进了一下,提前退出,不进入递归
if (candidates[i] + sum > target) {
return;
}
//这是针对同一层不能选择重复的
if (i > start && candidates[i] == candidates[i - 1]) {
continue;
}
temp.add(candidates[i]);
traceBack2(res, temp, candidates, target, sum + candidates[i], i + 1);
temp.remove(temp.size() - 1);
}
}
39. 组合总和
40. 数组总和2
46. 全排列
47. 全排列2
77. 组合
78. 子集
90. 子集 II
784. 字母大小写全排列
51. N皇后