给定一个数组 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]
]
题解:很容易想到用深搜遍历所有的情况,但在这里需要注意的问题是,数组本身的元素是有重复的,两个相同的数组元素与其它元素组合组成的满足要求的解相同的,如示例1:[1,7]和[7,1]是相同的解。那么接下来的问题就是避免重复解的问题了,我的思路是先将数组排序,当每次递归开始的元素与其前一个元素相同时,直接跳过,这样就避免重复使用相同元素开始组成解了。接下来就是对整个递归进行优化了,当目标值target减去某一个数组值后小于0时,就可以直接跳过了。
class Solution {
static List<List<Integer>> res;
public static void dfs(int[] candidates,List<Integer> tmp,int target,int s){
if(target<0)
return;
if(target==0){
res.add(new ArrayList<>(tmp));
return ;
}
for(int i=s;i<candidates.length;i++){
if(candidates[i]>target||(i>s&&candidates[i]==candidates[i-1]))
continue;
tmp.add(candidates[i]);
dfs(candidates,tmp,target-candidates[i],i+1);
tmp.remove(tmp.size()-1);
}
}
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
res=new ArrayList<>();
dfs(candidates,new ArrayList<>(),target,0);
return res;
}
}