给定一个数组 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]
]
和I的不同是,给出的数组当中是有重复元素的。
成功
执行用时 : 7 ms, 在Combination Sum II的Java提交中击败了88.21% 的用户
内存消耗 : 37.3 MB, 在Combination Sum II的Java提交中击败了90.16% 的用户
class Solution {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
List<List<Integer> > res = new ArrayList<List<Integer> >();
if(candidates.length == 0 || target < candidates[0] )
return res;
List<Integer> tmp = new ArrayList<Integer>();
helper(candidates, target, 0, tmp, res);
return res;
}
public void helper(int[] a, int target, int start, List<Integer> tmp, List<List<Integer> > res){
if(target < 0)
return;
if(target == 0){
res.add(new ArrayList<Integer>(tmp) );
return;
}
for(int i=start; i<a.length; i++){
tmp.add(a[i]);
int newtarget = target-a[i];
helper(a, newtarget, i+1, tmp, res);
tmp.remove(tmp.size()-1);
if(newtarget <= 0)
break;
while(i+1<a.length && a[i]==a[i+1])//组合中有重复元素,不要重复开头
i++;
}
}
}
关键在于下面这段代码放的位置。每组解当中可以有重复元素(因为数组本来就是含有重复元素的),但是每组解不可以重复,我们只需不让重复元素重复作为每组解的第一个元素即可。
while(i+1<a.length && a[i]==a[i+1])//组合中有重复元素,不要重复开头
i++;