今日内容:
- 理论基础
- 77. 组合
一、理论基础
回溯法解决的问题都可以抽象为树形结构
回溯三部曲:
1、 回溯函数模板返回值以及参数
2、回溯函数终止条件
3、回溯搜索的遍历过程
void backtracking(参数) { if (终止条件) { 存放结果; return; } for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) { 处理节点; backtracking(路径,选择列表); // 递归 回溯,撤销处理结果 } }
回溯模板
二、组合
回溯三部曲:
1、递归函数的返回值以及参数
vector<vector<int>> result; // 存放符合条件结果的集合
vector<int> path; // 用来存放符合条件单一结果
void backtracking(int n, int k, int startIndex)
2、终止条件
如果path的数量达到了要求的k就停止
if (path.size() == k) {
result.push_back(path);
return;
}
3、单层过程
for (int i = startIndex; i <= n; i++) { // 控制树的横向遍历
path.push_back(i); // 处理节点
backtracking(n, k, i + 1); // 递归:控制树的纵向遍历,注意下一层搜索要从i+1开始
path.pop_back(); // 回溯,撤销处理的节点
}
代码
class Solution {
public:
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();
}
}
vector<vector<int>> combine(int n, int k) {
result.clear();
path.clear();
backtracking(n,k,1);
return result;
}
};
题解中做了剪枝优化,大意是减去那些肯定不够数的,比如说从2开始要4个数,但是一共就是1-4,很明显就是只有【1,2,3,4】这一种情况。
所以在里面印出来已经选择的个数有path.size();
还需要k-path.size();
所以之多从n-(k-path.size())+1开始
for (int i = startIndex; i <= n - (k - path.size()) + 1; i++)
还可以,感觉和递归三部曲差不多