class Solution {
List<List<Integer>> res = new ArrayList<>();
int[] candidates;
int len;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
this.candidates = candidates;
this.len = candidates.length;
Arrays.sort(this.candidates);
backtrack(new ArrayList<Integer>(), -1, target); //假设有一个前置节点,从-1开始,不然在主程序得加个for(哑结点作为决策树根节点)
return this.res;
}
public void backtrack(List<Integer> pre, int index, int tar){
if(tar == 0){
res.add(pre);
return;
}
if(tar < 0){return;}
for(int i = index+1; i < len; i++){
if(i>index+1 && candidates[i]==candidates[i-1]) continue;
List<Integer> cur = new ArrayList(pre);
cur.add(candidates[i]);
backtrack(cur,i,tar-candidates[i]);
}
//return;
}
}
重点:
- 为了代码结构优化,引入-1的索引位置(就是在决策树引入显示根节点)(哑结点)
- 既要确保相同元素不在树的同一层,又要保证相同元素可以出现在下一层,所以回溯算法每次for时遇见相同元素只递归一次,