题目描述:
给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。数组中存在重复的数字!
candidates 中的每个数字在每个组合中只能使用 一次 。
注意:解集不能包含重复的组合。
来源:力扣(LeetCode)
思路:
保证同一级不会出现相同的数字;但是不同级可以出现相同的数字!
1)该题的难点是 减去重复出现的情况;之前做过该类型的题,先将数组排序;然后每次进行add时,跳过之前出现的情况,直到第一个不一样的情况!
要先排序
//如果这里使用 i > 0;会出现比较 candidates[start] 和 candidates[start - 1]的情况;最直观的就是丢失 116这种情况!
if(i > start && candidates[i] == candidates[i - 1]) continue;
2)剪枝:后面的情况必然不符合要求,就不再搜索!
代码:
1)回溯+剪枝+搜索中判断(跳过已出现的情况)
class Solution {
//难点在于,怎么在递归回溯搜索的过程中进行 判断是否已经出现过该结果
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
back(candidates,target,0);
return res;
}
void back(int[] candidates,int target,int start){
if(target == 0){
res.add(new LinkedList<>(path));
return;
}
for(int i = start;i < candidates.length;i++){
if(target - candidates[i] < 0) break;
if(i > start && candidates[i] == candidates[i - 1]) continue;
path.add(candidates[i]);
back(candidates,target - candidates[i],i + 1);
path.removeLast();//回溯
}
}
}