题目链接:LeetCode-40-组合总和Ⅱ
代码实现
java
class Solution {
/**
* 回溯算法:需要注意这个不能有重复的组合,但是组合中可以有相同的元素,其实也不是相同的元素,数值相同但索引不同
* 1. 数组排序,为了将相等的元素放到一起
* 2. 回溯:注意需要树层去重,树枝上不需要去重
* 注意:use数组加进去的时候要置为true,退回去要将状态恢复成false
* @param candidates
* @param target
* @return
*/
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
boolean[] used = new boolean[candidates.length];
Arrays.sort(candidates);// 排序,为了将相等的元素放到一起
backTracking(candidates,target,0,0, res, path, used);
return res;
}
/**
* @param candidates 候选人集合
* @param target 目标和
* @param startIndex 起始下标,防止组合中不能出现重复的元素
* @param curSum 当前路径的和
* @param res 结果集
* @param path 单层路径中的值
* @param used 数组中哪些元素已经被使用:true:用了 ; false:没用
*/
public static void backTracking(int[] candidates, int target, int startIndex, int curSum, List<List<Integer>> res, List<Integer> path,boolean[] used){
if (curSum > target){
return;
}
if (curSum == target){
res.add(new ArrayList<>(path));
return;
}
for (int i = startIndex; i < candidates.length; i++) {
// used[i-1]==false 是树层去重,前一个相同的元素没有使用,那么后一个元素才能用,否则两个取得组合完全一样
if (i > 0 && candidates[i]==candidates[i-1] && used[i-1]==false){// 当前元素和前一个元素相等,去重逻辑
continue;
}
used[i] = true;
path.add(candidates[i]);//这个不能放进去,必须单独添加,因为 list.add返回true表示添加成功,返回fasle表示添加失败,会影响后面的结果
backTracking(candidates, target, i+1, curSum+candidates[i], res, path, used);
path.remove(path.size()-1);
used[i] = false;// 恢复到false
}
}
}