回溯算法
剑指Offer P88
1.基础知识
强烈推荐labuladong同学的题解。
1- 回溯算法通常也不具有返回值,和dfs很像。可以将输入设置为全局变量,然后回溯函数的输入大概包括
backTrack(当前路径,选择列表)
2- backTrack 函数
2-1 判断截止条件,如果满足条件,则将当前结果路径压入结果
2-2 对于选择列表中的每一个可行选项
做选择,
backTrack(更新选择路径,更新选择列表);
撤销路径(因为在循环内,撤销刚才尝试,然后尝试当前路径中的下一个可行选项)
# 回溯算法伪代码
result = []
def backtrack(路径, 选择列表):
if 满足结束条件:
result.add(路径)
return
for 选择 in 选择列表:
做选择
backtrack(路径, 选择列表)
撤销选择
另附最近看过的某位大神的讲解,感觉讲的不错。👇
dfs讲解
其中,对于全排列这种问题,可以使用一个与输入等长数组vector<bool>来存储当前的路径。
2.例题
2.1 矩阵中的路径
2.2 机器人的运动范围
2.3 括号生成
解题思路:想好递归数,如递减树,记录剩余的左右括号可使用的个数。
当没有左右括号可以使用时,将此时的字符串输出,否则只有当可用的右括号不少于左括号时,才可以加入左括号,并递归;否则,可以加入右括号,并递归。
对Backtrack算法和DFS算法不够熟练,此题当做课后作业了。请补足代码于下方:
// backtrack
2.4 全排列
2.5 组合
套用模板!!
vector<vector<int>> combine(int n, int k) {
vector<vector<int>> res;
vector<int> valid_res;
count(res, valid_res, n, k, 1);
return res;
}
void count(vector<vector<int>> &res, vector<int> &valid_res, int &n, int &k, int idx){
if(valid_res.size() >= k){
res.push_back(valid_res);
return;
}else{
for(int i = idx; i <= n; ++i){
valid_res.push_back(i);
count(res, valid_res, n, k, i+1);
valid_res.pop_back();
}
}
}
下面为英文解答的神来之笔!
vector<vector<int>> combine(int n, int k) {
vector<vector<int>> a;
vector<int> b(k,0);
int i=0;
while (i >= 0)
{
b[i]++;
if (b[i] > n) i--;
else if (i == k - 1) a.push_back(b);
else
{
i++;
b[i] = b[i - 1];
}
}
return a;
}