回溯
使用减法,确定下一次dfs要找的数。比如下面的例子,[2, 3, 6, 7],7 - 2 = 5,5就是下一次dfs要找的数,如果能把5减到0,那么就找到一组答案[2, 2, 3]。
-
第一个问题,如何避免重复?比如
[2, 2, 3]和[2, 3, 2]。我们可以在每次dfs入口,将for循环起始数设置为当前下标。比如[2, 3, 2],在3准备往下递归时,将起始数(begin)设置为1,下一次递归就是从3开始,当然最后一个3要剪枝(如下图)。 -
第二个问题,如何剪枝?如下图左下角,
1 - 2 = -1, 1 - 3 = -2, 1 - 6 = -5, 1 - 7 = -6,所以我们可以从第一个-1就开始剪枝,用break退出当前循环即可。当然前提是将数组排好序。
class Solution {
List<List<Integer>> res = new ArrayList<>();
Deque<Integer> combination = new ArrayDeque<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
dfs(candidates, target, 0);
return res;
}
public void dfs(int[] candidates, int target, int begin) {
if (target == 0) {
res.add(new ArrayList(combination));
return;
}
for (int i = begin; i < candidates.length; i++) {
if (target - candidates[i] < 0) {
break;
}
combination.addLast(candidates[i]);
dfs(candidates, target - candidates[i], i);
combination.removeLast();
}
}
}