day24
今天开启回溯章节咯!
回溯和递归密不可分!
回溯三部曲:(个人感觉和递归差不多)
1. 确定返回值和参数
这里的返回值一般都是 void
参数 一开始可能不能完全确定下来,所以需要用到哪些,就把哪些写上
2.终止条件
一般在终止条件中收割结果,然后 return掉
3.单层的逻辑
一般是先是个for循环,然后在for循环里面继续递归
回溯其实就是依靠一个for循环 和 递归 形成了一个N 叉树的结构
回溯模板
void backtracking(参数)
{
if(终止条件)
{
收集结果
return;
}
for(遍历次数是每个集合的大小)
{
处理结点
递归
回溯
}
return;
}
回溯
剪枝
剪枝就是用来优化回溯的。因为可以在回溯之前就可以人为判断,哪些清空下就不需要再进行递归了。
class Solution {
public:
vector<int> path;
vector<vector<int>> res;
void backtracking(int n, int k, int startIndex)
{
if(path.size() == k) // 终止条件
{
res.push_back(path);
return;
}
// 在 i 所能取到的范围做了剪枝
for(int i = startIndex; i <= n + 1 - (k - path.size()); i++) // 循环
{
path.push_back(i);
backtracking(n, k, i + 1);
path.pop_back(); // 回溯的逻辑在递归的下面,因为递归返回之后再做回溯操作
}
return;
}
vector<vector<int>> combine(int n, int k) {
backtracking(n , k , 1);
return res;
}
};