
组合总和
问题描述:给一个组合元素集合【2 5 3】,都是正整数且没有重复,有一个targer数8, 集合里面的元素可以重复选,让我们从组合里挑数,使得求和后等于8,返回能求和的组合 , 答案应该是:【 【2,2,2,2】, 【2,3,3】 , 【3,5】 】
画树形结构的注意点:
1、路径取了2后,剩余元素仍然是2 3 5,因为元素可以重复取。
2、第2条分支,取5,剩余元素要从5后开始算,即5 3, 不能有2,因为如果5 2 那么就和前面的2 5重复了。
3、叶子结点判断是否等于target,如果等于,记录这个答案,返回。如果大于target,已经超了,直接返回。如果小于,继续树深查找。

用代码 实现
和组合问题比较大的差异是:选了一个元素后,剩余元素里,要把已经选过的元素带上,这样才能达到重复选取目地。
其他方面和组合问题差不多,只不过是用一个组合的和target,限制树的高度。
回溯三部曲实现:
1、函数返回值 一般是void
2、确定终止条件
3、单层搜索逻辑
C++
vector<vector<int>> result;
vector<int> path;
sum判断path路上的和是否等于target。
int sum;
startIndex 作用:在第2个分支如何知道从下一个位置开始找,是for循环变量的开始位置。
void backtracking(candidate, target, sum, startIndex){
if(sum > taeget) return;
if(sum == target){
result.push_back(path);
return;
}
//单层搜索逻辑,for循环里面的i控制左右,即for的i控制分支, 里面的递归控制高度
for(int i = startIndex; i<candidate.size();i++){
path.push_back(candidate[i]);
sum += candidate[i];
backtracing(candidate, target, sum, i);
//回溯不能掉,如何收集信息,就如何吐出去。
sum -= candidate[i];
path.pop_back();
}
return;
}
这里附上我的完整的解题代码
C++
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
int sum=0;
int startIndex=0;
void backtracking(vector<int>& candidates, int target, int sum, int startIndex){
if(sum > target) return;
if(sum == target){
result.push_back(path);
return;
}
//单层搜索逻辑
for(int i=startIndex; i<candidates.size(); i++){
path.push_back(candidates[i]);
sum += candidates[i];
backtracking(candidates, target, sum, i);
//回溯,撤销删除
sum -= candidates[i];
path.pop_back();
}
return;
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
backtracking(candidates, target, 0, 0);
return result;
}
};