-
这里有陷阱就是提供数组会有重复元素,而输出的组合不能有重复,所以要在搜索的过程中就去掉重复组合。
-
组合问题可以抽象为树形结构,那么“使用过”在这个树形结构上是有两个维度的,一个维度是同一树枝上使用过,一个维度是同一树层上使用过。
-
树枝上表示纵向的回溯,可以出现重复元素:[1, 1, 6]
-
树层表示横向的遍历,不能出现重复元素:[1, 2, 5]、[1, 2, 5],否则就会出现重复的组合
-
强调一下,树层去重的话,需要对数组排序!
-
这里使用startIndex进行去重(也可以使用used数组)
-
在同层遍历 i大于startIndex的情况下,如果当前元素和前一个元素相同,则跳过这个元素, i大于startIndex可以跳过树枝上的重复情况,只判断树层上的重复情况
class Solution {
LinkedList<Integer> path = new LinkedList<>();
List<List<Integer>> res = new ArrayList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates); // 先进行排序
backtracking(candidates, target, 0, 0);
return res;
}
public void backtracking (int[] candidates, int target, int sum, int startIndex) {
if (sum == target) {
res.add(new ArrayList<>(path));
return;
}
// 这里仍然采用上一题的去重
for (int i = startIndex; i < candidates.length && sum + candidates[i] <= target; i++) {
// 要对同一树层使用过的元素进行跳过
if (i > startIndex && candidates[i] == candidates[i - 1]) {
continue;
}
path.add(candidates[i]);
sum += candidates[i];
backtracking(candidates, target, sum, i + 1);
path.removeLast();
sum -= candidates[i];
}
}
}