给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
注意:解集不能包含重复的组合。
对比39题,唯一的区别在于解集不能重复,因此对比39题我们要考虑到使用used数组来保证不会产生相同结果
(117条消息) LeetCode39.组合总数(回溯与剪枝)_m0_51630248的博客-CSDN博客
class Solution {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
int len=candidates.length;
List<List<Integer>>ans=new ArrayList<>();
List<Integer>path=new ArrayList<>();
Arrays.sort(candidates);
boolean[]used=new boolean[len];
dfs(ans, path,used,candidates,target,0,0);
return ans;
}
void dfs(List<List<Integer>>ans,List<Integer>path,boolean[]used,
int[]candidates,int target,int sum,int start){//下标从start开始
if(sum>target){
return;
}else if(sum==target){
ans.add(new ArrayList<>(path));
}
for(int i=start;i<candidates.length;i++){//保持答案内部的有序性
if(i>0&&candidates[i]==candidates[i-1]&&!used[i-1])continue;
sum+=candidates[i];
path.add(candidates[i]);
used[i]=true;
dfs(ans, path,used,candidates, target,sum,i+1);
used[i]=false;
sum-=candidates[i];
path.remove(path.size()-1);
}
}
}
核心是这句话
if(i>0&&candidates[i]==candidates[i-1]&&!used[i-1])continue;
作用多多,遍历的时候如果前一个数相同则直接跳过,但注意到如果前一个数字使用还是可以重用的,注意到!used[i-1]去掉就会产生这样的结果,就是因为1,1相同,遍历时直接跳过第二个1,这显然是错误的,因此要注意这句话,非常之精髓,非常之重要啊老铁们!