目录
回溯算法理论基础
递归与回溯相辅相成,回溯一般在递归函数的下面。
回溯算法是一个暴力搜索的方法,效率并不高。
解决的问题:
组合问题:N个数里面按一定规则找出k个数的集合
切割问题:一个字符串按一定规则有几种切割方式
子集问题:一个N个数的集合里有多少符合条件的子集
排列问题:N个数按一定规则全排列,有几种排列方式
棋盘问题:N皇后,解数独等等
回溯法可以抽象为一个树形结构,n叉树。树的宽度是集合的大小,一般用for循环遍历;树的深度就是递归的深度。
回溯法的模板
void backtracking(参数){
if(终止条件){
收集结果;
return;
}
for(集合元素){
处理节点;
递归函数;
回溯撤销处理结果;
}
return;
}
题目链接:77. 组合
思路
确定递归函数的参数和返回值
确定递归的终止条件
确定单层递归的逻辑
代码
class Solution {
public:
vector<vector<int>> result; // 结果集
vector<int> path; // 单个组合
void backtracking(int n, int k, int startindex) {
if (path.size() == k) {
// 单个组合收集到的元素等于k时
// 将单个组合存放到结果集中
result.push_back(path);
return;
}
for (int i = startindex; i <= n; i++) {
path.push_back(i); // 将元素存放到path中
backtracking(n, k, i + 1); // 递归
path.pop_back(); // 回溯撤销处理结果,以便存放下一个组合
}
return;
}
vector<vector<int>> combine(int n, int k) {
backtracking(n, k, 1);
return result;
}
};
总结
①在二叉树章节一直在使用递归,在这里加入了回溯操作,也能理解
②对于数组的处理还是比较熟悉,在解决后面的问题时,加深对字符串和回溯的理解