40.组合总和Ⅱ
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
说明:
所有数字(包括目标数)都是正整数。
解集不能包含重复的组合。
- 跟上一题组合总和一样的解法
- 这次规定只能使用一次数字,那么我们可以添加一个判定的数组
- 数组的大小和candidates大小一致,判定数组的每一位对应candidates的每一位,在使用到这个数字的时候,在判定数组的相应位置写上1,代表我使用了这个数,在搜索完毕的时候归0,表示归还.
class Solution {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<List<Integer>> result = new ArrayList<>();
for (int i = 0; i < candidates.length; i++){
List<Integer> temp = new ArrayList<>();
// 判定用数字
int[] pos = new int[candidates.length];
temp.add(candidates[i]);
// 使用时写上1
pos[i] = 1;
searchCandidatesToSum2(result,temp,candidates[i],pos,candidates,target);
temp.remove((Integer) candidates[i]);
// 搜索结束归0
// 下面的函数内部逻辑 同理
pos[i] = 0;
}
return result;
}
private void searchCandidatesToSum2(List<List<Integer>> result, List<Integer> temp, int tempSum, int[] pos, int[] candidates, int target) {
// 与之前的文章一样的逻辑
// 在此不多赘述
if( tempSum > target ){
return;
}
if( tempSum == target ){
if( findResult(result,temp) ){
temp.sort(Comparator.naturalOrder());
result.add(new ArrayList<>(temp));
}
return;
}
for (int i = 0; i < candidates.length; i++) {
if( pos[i] != 1 ){
temp.add(candidates[i]);
pos[i] = 1;
searchCandidatesToSum2(result,temp,tempSum+candidates[i],pos,candidates,target);
pos[i] = 0;
temp.remove((Integer)candidates[i]);
}
}
}
// 复制了之前的代码
// 函数重用 XD
private boolean findResult(List<List<Integer>> result, List<Integer> temp) {
for (List<Integer> item :
result) {
/**
* 当集合大小相同时进行比对
*/
if( item.size() == temp.size() ){
List<Integer> newItem = new ArrayList<>(item);
for (Integer i : temp) {
/**
* 当newItem中存在temp的第i个目标时
* 从newItem中删去当前目标相同的数字
*/
if(newItem.contains(i)){
newItem.remove(i);
}
}
/**
* 若newItem的大小为0时
* 说明newItem与temp的内容完全相同
* 则返回false
*/
if( newItem.size() == 0 ){
return false;
}
}
}
return true;
}
}