给定一个数组 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]
]
示例 2:

输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
  [1,2,2],
  [5]
]
这道题和上道题比较像,只不过不能重复用
第一次提交犯了一个错误,我直接使用了TreeSet去重,但会覆盖不到有多个同样数且需要多个同样数才能组成结果的时候,去重会抹掉数量信息,我们只要保证在dfs同层不会使用同一个数,结果就不会重复。

private List<List<Integer>> result=new ArrayList();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
    List<Integer> all=Arrays.stream(candidates).sorted().boxed().collect(Collectors.toList());
    helper(all,new ArrayList(),0,target);
    return result;  

}

private void helper(List<Integer> all,List<Integer> cur,int index,int target){
    if(target==0){
        result.add(cur);
        return;
    }
    for(int i=index;i<all.size() && target>=all.get(i);i++){
        if(i>index && all.get(i)==all.get(i-1)) continue;
        List<Integer> list=new ArrayList();
        list.addAll(cur);
        list.add(all.get(i));
        helper(all,list,i+1,target-all.get(i));
    }
}
错误的
private List<List<Integer>> result=new ArrayList();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
    Set<Integer> set=new TreeSet();
    for(int i:candidates) set.add(i);
    helper(new ArrayList(set),new ArrayList(),0,target);
    return result;  

}

private void helper(List<Integer> all,List<Integer> cur,int index,int target){
    if(target==0){
        result.add(cur);
        return;
    }
    for(int i=index;i<all.size() && target>=all.get(i);i++){
        List<Integer> list=new ArrayList();
        list.addAll(cur);
        list.add(all.get(i));
        helper(all,list,i+1,target-all.get(i));
    }
}

程浩
21 声望2 粉丝