题目链接
回溯
本题的难点在于:集合(数组candidates)有重复元素,但还不能有重复的组合。
思想:元素在同一个组合内是可以重复的,怎么重复都没事,但两个组合不能相同。所以要去重的是同一树层上的“使用过”,同一树枝上的都是一个组合里的元素不用去重。
树层去重的话,需要对数组排序
去重逻辑:
如果candidates[i] = =candidates[i - 1] && used[i - 1] = = false,就说明:前一个树枝,使用了candidates[i - 1],也就是说同一树层使用过candidates[i - 1]。
used[i - 1] = true,说明同一树枝candidates[i - 1]使用过 used[i - 1] =
false,说明同一树层candidates[i - 1]使用过
为什么 used[i - 1] = false 就是同一树层呢?
- 因为同一树层,used[i - 1] = false 才能表示,当前取的 candidates[i] 是从 candidates[i - 1] 回溯而来的。
- 而 used[i - 1] == true,说明是进入下一层递归,去下一个数,所以是树枝上
class Solution {List<List<Integer>> res = new ArrayList<List<Integer>>();List<Integer> list = new ArrayList<Integer>();boolean[] used;public List<List<Integer>> combinationSum2(int[] candidates, int target) {used = new boolean[candidates.length];Arrays.fill(used, false);Arrays.sort(candidates);backtracking(candidates, target, 0, 0);return res;}public void backtracking(int[] candidates, int target, int sum, int startIndex){if(sum > target){return;}if(sum == target){res.add(new ArrayList<>(list));return;}// used[i - 1] == true,说明同一树枝candidates[i - 1]使用过// used[i - 1] == false,说明同一树层candidates[i - 1]使用过for(int i = startIndex; i < candidates.length; i++){if (i > 0 && candidates[i] == candidates[i - 1] && !used[i - 1]) {continue;}// 下一层递归used[i] = true;sum += candidates[i];list.add(candidates[i]);backtracking(candidates, target, sum, i + 1);used[i] = false;sum -= candidates[i];list.removeLast();}}
}