39.组合总和 && 40.组合总和II
39
思路:回溯
class Solution {
public:
vector<vector<int>> res;
vector<int> tmp;
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
backtrack(0,0,candidates,target);
return res;
}
void backtrack(int start,int sum,vector<int>& candidates,int target){
if(sum==target){
res.push_back(tmp);
return;
}
if(sum>target){
return;
}
for(int i=start;i<candidates.size();i++){
sum=sum+candidates[i];
tmp.push_back(candidates[i]);
backtrack(i,sum,candidates,target);
sum=sum-candidates[i];
tmp.pop_back();
}
}
};
40
思路:回溯+去重
以下摘自代码随想录
组合问题可以抽象为树形结构,那么“使用过”在这个树形结构上是有两个维度的,一个维度是同一树枝上使用过,一个维度是同一树层上使用过。没有理解这两个层面上的“使用过” 是造成大家没有彻底理解去重的根本原因。
那么问题来了,我们是要同一树层上使用过,还是同一树枝上使用过呢?
回看一下题目,元素在同一个组合内是可以重复的,怎么重复都没事,但两个组合不能相同。
所以我们要去重的是同一树层上的“使用过”,同一树枝上的都是一个组合里的元素,不用去重。
强调一下,树层去重的话,需要对数组排序!
class Solution {
public:
vector<int>tmp;
vector<bool>used;
vector<vector<int>>res;
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
used.resize(candidates.size());
sort(candidates.begin(), candidates.end());
backtrack(0,0,candidates,target);
return res;
}
void backtrack(int start,int sum, vector<int>& candidates, int target){
if(sum==target){
res.push_back(tmp);
return;
}
if(sum>target) return;
for(int i=start;i<candidates.size();i++){
if(i>0 && used[i-1]==false && candidates[i]==candidates[i-1]){//一层重复,跳过
continue;
}
sum=sum+candidates[i];
used[i]=true;
tmp.push_back(candidates[i]);
backtrack(i+1,sum,candidates,target);
sum=sum-candidates[i];
used[i]=false;
tmp.pop_back();
}
}
};