学习安排根据《代码随想录》
1. 回溯的本质是递归,与递归函数相辅相成;
2.回溯常用来解决以下几种问题:组合、排列、切割、子集、棋盘等问题;
3.回溯法都可以抽象问一个N叉树问题;
4.回溯法一般无返回值,参数的确定很重要:void backtracking(......);
5.回溯三部曲:
1.确定递归函数的参数及返回值
2.确定终止条件
3.确定单层递归逻辑
6.回溯法的写法模板:
void backtracking(参数)
{
//终止条件
if(终止条件)
{
收集结果;
return ;
}
//单层递归逻辑
for(元素集/集合的宽度)
{
结点的处理;
backtracking(参数);// 递归 / 深度
回溯处理;
}
return;
}
以 leetcode 77 组合问题为例:
代码:
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();
}
return ;
}
vector<vector<int>> combine(int n, int k)
{
backtracking(n,k,1);
return result;
}
};
7.剪枝操作:去掉重复且无用的步骤,常在for循环里做文章,即是否可以缩小 n 的值。
例:如果 n=4 ,k=4 剪枝操作为:
for(int i= startindex;i<=path.size();i++) =====》for(int i=startindex;i<=n-(k-path.size())+1;i++)
其中,n-(k-path.size)+1 表示 至多从该位置取数。