Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.
Each number in C may only be used once in the combination.
Note:
All numbers (including target) will be positive integers.
The solution set must not contain duplicate combinations.
For example, given candidate set [10, 1, 2, 7, 6, 1, 5] and target 8,
A solution set is:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
解:和Combination Sum问题类似,不同点在于:每一个元素只能用一次。 因而,对第i个元素,进行匹配时需要对第i+1到len个元素进行遍历,依次类推进行递归。且对于相同元素进行跳过,防止相同的结果集出现。
public class Solution {
List<List<Integer>> result = null;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
if (candidates.length == 0 || null == candidates) return result;
result = new ArrayList<>();
Arrays.sort(candidates);//排序 为了遍历的时候去除重复
for (int i = 0;i<candidates.length;i++) {
if (candidates[i]>target) break; //比target大 立即停止遍历
if (i > 0){ //把重复元素过滤
while(i<candidates.length && candidates[i]==candidates[i-1]) i++;
if (i == candidates.length) break;
}
List<Integer> list = new ArrayList<>();
list.add(candidates[i]);
dfs(candidates,i,target-candidates[i],list);
}
return result;
}
void dfs(int[] candidates,int start,int target,List<Integer> list){
if (target == 0){
result.add(new ArrayList<Integer>(list));
return;
}else if (target < 0){
return;
}else {
//start+1为了每次遍历从当前元素下一个开始
for (int i = start+1;i<candidates.length;i++) {
if (candidates[i]>target) break;
if (i > start + 1){//当前遍历中去除重复元素
while(i<candidates.length && candidates[i]==candidates[i-1]) i++;
if (i == candidates.length) break;
}
list.add(candidates[i]);
dfs(candidates,i,target-candidates[i],list);
//递归条件不满足,返回上一步继续递归
list.remove(list.size()-1);
}
}
}
}