40. 组合总和 II
给定一个数组 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为 target
的组合。
candidates
中的每个数字在每个组合中只能使用一次。
**注意:**解集不能包含重复的组合。
示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]
示例 2:
输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]
提示:
1 <= candidates.length <= 100
1 <= candidates[i] <= 50
1 <= target <= 30
class Solution {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
// diff:代表所有不同的数字
// num:代表每种数字有多少个
List<Integer> diff = new ArrayList<Integer>();
List<Integer> num = new ArrayList<Integer>();
diff.add(candidates[0]);
num.add(1);
for(int i = 1; i < candidates.length; ++i){
// 说明是新数字,添加新的,否则加个数
if(candidates[i] != diff.get(diff.size() - 1)){
diff.add(candidates[i]);
num.add(1);
} else {
num.set(num.size() - 1, num.get(num.size() - 1) + 1);
}
}
// result:最终的结果集
// select:暂时选定的结果
// sum:select中的和
List<List<Integer>> result = new ArrayList<List<Integer>>();
List<Integer> select = new ArrayList<Integer>();
int sum = 0;
huisu(target, result, select, sum,0, diff, num);
return result;
}
public void huisu(int target, List<List<Integer>> result, List<Integer> select, int sum, int index, List<Integer> diff, List<Integer> num){
if(sum == target){
result.add(new ArrayList(select));
return;
}
// 否则说明根本没有机会
if(index < diff.size() && sum + diff.get(index) <= target){
for(int i = index; i < diff.size(); ++i){
if(sum + diff.get(i) <= target){
// 候选种增加内容,并且可用减1
select.add(diff.get(i));
num.set(i,num.get(i) - 1);
// 不在可用,就只能选择下一个
if(num.get(i) == 0){
huisu(target, result, select, sum + diff.get(i), i + 1, diff, num);
} else{
huisu(target, result, select, sum + diff.get(i), i, diff, num);
}
select.remove(select.size() - 1);
num.set(i, num.get(i) + 1);
} else {
break;
}
}
}
}
}