第77题. 组合
class Solution {
private:
int startIndex=1;
vector<vector<int>> result;
vector<int> path;
void backtracking(int n,int k,int startIndex){
if(path.size()==k){
result.push_back(path);
return;
}
for(int i=startIndex;i<=n;i++){
path.push_back(i);
backtracking(n,k,i+1);
path.pop_back();
}
return;
}
public:
vector<vector<int>> combine(int n, int k) {
backtracking(n,k,startIndex);
return result;
}
};
回溯三部曲,第一步确定递归的参数和返回值,参数为数组,组合size大小,起始值,返回值无;第二步,回溯的终止条件,就是当到叶子节点时就停止push_back,即递归到组合size大小的那一层就返回;第三步就是单层搜索过程,单层搜索就是横向搜索,用for循环横向遍历,再用path添加,再回溯
class Solution {
private:
int startIndex=1;
vector<vector<int>> result;
vector<int> path;
void backtracking(int n,int k,int startIndex){
if(path.size()==k){
result.push_back(path);
return;
}
for(int i=startIndex;i<=n+1-k+path.size();i++){
path.push_back(i);
backtracking(n,k,i+1);
path.pop_back();
}
return;
}
public:
vector<vector<int>> combine(int n, int k) {
backtracking(n,k,startIndex);
return result;
}
};
这是组合问题的剪枝优化,就优化了一行代码,因为要找的组合大小,在递归过程中如果startIndex后面的数组大小加当前记录的path大小小于组合大小,这部分递归就没有必要进行,具体就是:此时已记录的大小为path.size(),后面至少还应有的空间为k-path.size(),而此时留有的的空间为n-startIndex+1,所以现留有的空间应至少大于理论上的空间,所以n-startIndex+1>=k-path.size(),所以,startIndex<=n+1-k+path.size()。这就是要做的剪枝
216.组合总和III
class Solution {
private:
vector<int> path;
vector<vector<int>> result;
void backtracking(int k,int n,int starIndex,int end,int Sum){
if(path.size()==k){
if(Sum==n) result.push_back(path);
return;
}
for(int i=starIndex;i<=end+1-k+path.size();i++){
Sum+=i;
path.push_back(i);
backtracking(k,n,i+1,end,Sum);
Sum-=i;
path.pop_back();
}
return;
}
public:
vector<vector<int>> combinationSum3(int k, int n) {
backtracking(k,n,1,9,0);
return result;
}
};
回溯的参数为目标和,组合里数的个数,起始数,结束数,数之和,返回值无,递归终止条件为当path里数的个数等于目标个数时必须返回,如果Sum的值等于目标和时,result记录该path,递归的单层搜索过程为用for循环横向遍历,Sum累加值,path记录i,然后递归,最后回溯,Sum变为累加前的大小,path弹出之前记录的i。