
java
class Solution {
List<List<Integer>> res = new ArrayList<>();
List<Integer> path = new ArrayList<>();
//实时记录总和
int sum = 0;
public List<List<Integer>> combinationSum(int[] candidates, int target) {
backtrack(candidates, target, 0);
return res;
}
private void backtrack(int[] candidates, int target, int startIndex){
if(sum > target){
return;
}
if(sum == target){
res.add(new ArrayList<>(path));
return;
}
//startIndex:防止回头,防止出现2,2,3和3,2,2同时出现的情况
for(int i = startIndex; i < candidates.length; i++){
path.add(candidates[i]);
sum += candidates[i];
//因为元素可以重复,所以这里从i开始
backtrack(candidates, target, i);
path.remove(path.size() - 1);
sum -= candidates[i];
}
}
}

对比:
全排列:每次从头挑,没有startIndex,自己不能选自己,需要used数组
子集:每次只能往后挑,不能回头,需要startIndex,拿过一个必须走向下一个(传i+1)
组合总和:每次只能往后挑,不能回头,需要startIndex,但当前可以无限选(传i)