方法一:回溯
1,2和2,1是同一个组合,因此需要引入start参数标识,每个状态中选择列表的起始位置。
当当前和大于目标和时要枝剪。
数字可以重复使用,所以递归时从当前元素开始i而不是i+1。
class Solution {
public:
vector<vector<int>> res; //保存结果
void backtrack(vector<int>& track,vector<int>& candidates,int target,int start){
if(0==target){ //递归的终止条件
res.push_back(track);
return ;
}
if(target<0) return; //枝剪
for(int i=start;i<candidates.size();i++){
track.push_back(candidates[i]);
//因为每个数字都可以使用无数次,所以递归还可以从当前元素开始
backtrack(track,candidates,target-candidates[i],i);
track.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
if(candidates.empty() || target<0) return res;
vector<int> track; //路径
backtrack(track,candidates,target,0);
return res;
}
};
class Solution {
private:
vector<int> candidates;
vector<vector<int>> res;
vector<int> path;
void DFS(int start,int target){
if(target==0){
res.push_back(path);
return;
}
for(int i=start;i<candidates.size() && target-candidates[i]>=0; i++){
path.push_back(candidates[i]);
DFS(i,target-candidates[i]);
path.pop_back();
}
}
public:
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
sort(candidates.begin(),candidates.end());
this->candidates=candidates;
DFS(0,target);
return res;
}
};