给定一个数组 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]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combination-sum-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
回溯,因为数字不能重复,所以在递归遍历时,要将begin+1;剪枝条件:
①数组有序
②如果target-candidates[i]<0 则跳过本循环(而不是本次循环)
③如果candidates[i] == candidates[i - 1] 则跳过本次循环,因为在candidates[i-1]的分支里,已经包含了所有可能出现的结果,candidates[i]分支的结果为candidates[i-1]的真子集
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<List<Integer>> list = new ArrayList<>();
if (candidates == null || candidates.length == 0){
return list;
}
Deque<Integer> path = new ArrayDeque<>(candidates.length);
Arrays.sort(candidates);
dfs(candidates,target,0,path,list);
return list;
}
private void dfs(int[] candidates, int target, int begin, Deque<Integer> path, List<List<Integer>> list) {
if (target == 0){
list.add(new ArrayList<>(path));
return;
}
for (int i = begin; i < candidates.length; i++) {
if (target - candidates[i] < 0) {
break;
}
if (i > begin && candidates[i] == candidates[i - 1]) {
continue;
}
path.addLast(candidates[i]);
dfs(candidates,target - candidates[i],i+1,path,list);
path.removeLast();
}
}