1.递归简介
在许多问题上面,递归算法可以帮组我们快速高效地解决问题,例如涉及树、棋盘、迷宫、排列、组合、子串等问题,每一类问题都可以体现出相同的一种规律。
递归的关键在于设置合适的终止条件,这得需要大量经验的积累,我也是在不断学习~
2.模板
2.1 深搜的索引取(pos+1)
依次遍历的顺序如下(从上至下,从左至右):关键就在于DFS(res, pos+1),pos位置的变化会导致不同的回溯
0 1 2 3 1 1 2 3 2 1 2 3 3 1 2 3
0 1 3 3 1 1 3 3 2 1 3 3 3 1 3 3
0 2 2 3 1 2 2 3 2 2 2 3 3 2 2 3
0 2 3 3 1 2 3 3 2 2 3 3 3 2 3 3
0 3 2 3 1 3 2 3 2 3 2 3 3 3 2 3
0 3 3 3 1 3 3 3 2 3 3 3 3 3 3 3
#include <iostream>
#include <vector>
using namespace std;
void DFS(vector<int>& res, int pos) {
if (pos >= 4) {
return;
}
for (int i = pos; i < 4; ++i) {
res.push_back(i);
DFS(res, pos+1);
res.pop_back();
}
}
int main()
{
vector<int> res;
DFS(res, 0);
return 0;
}
2.2 全排列
在2.1的基础之上,我们只需稍加改动就成为全排列算法,分析2.1的执行过程我们可以发现,搜索的下一个状态的起始遍历位置取决于上一个pos+1的值,所以按照上面那种回溯,我们是无法从在每个位置从0开始遍历的,全排列最直接的方法无非就是在每一个位置上面要保证从0-n进行选择,为了将当前的起始遍历位置从0开始,i设置为0,但会带来前面出现过的元素会再次出现,例如前面已经出现过1,后面就要避免出现1,那么我们就可以设置变量记录当前元素的状态,如果没有出现过,取当前元素,若出现过,就跳过,当回溯到上一个状态的时候,重新恢复它的状态.
当然还有其他比较简单的写法,但这种写法是比较容易的,而且可以加深对递归的理解.
#include <iostream>
#include <vector>
using namespace std;
void DFS(vector<int>& res, vector<int> flag, int pos) {
if (pos >= 4) {
return;
}
for (int i = 0; i < 4; ++i) {
if (flag[i] == true) continue;
flag[i] = true; //标记当前位置
res.push_back(i);
DFS(res, flag, pos+1);
res.pop_back();
flag[i] = false;
}
}
int main()
{
vector<int> flag(4, false);
vector<int> res;
DFS(res, flag, 0);
return 0;
}
2.3 深搜的索引取(i+1)
依次遍历的顺序如下(从上至下):2.1只是帮助我们理解递归的过程,以下的这种情况就很有用了
0 1 2 3
0 1 3
0 2 3
0 3
1 2 3
1 3
2 3
3
#include <iostream>
#include <vector>
using namespace std;
void DFS(vector<int>& res, int pos) {
if (pos >= 4) {
return;
}
for (int i = pos; i < 4; ++i) {
res.push_back(i);
DFS(res, i+1);
res.pop_back();
}
}
int main()
{
vector<int> res;
DFS(res, 0);
return 0;
}
2.4 组合
对2.3的算法稍做点改动,就是组合算法啦,观察可以知道,上述过程是逐渐递增的,这过程和我们的组合过程是很类似的,例如从4个数里面选择两个数.设m=4、n=2,那么正常的思路就是[0 1]——>[0 2]——>[0 3]——>[1 2]——>[1 3]——>[2 3],这和2.3的执行过程是很相似的,如果仔细观察,就会发现其实这个过程和上面不同的地方在于终止条件不一样而已
#include <iostream>
#include <vector>
using namespace std;
void DFS(vector<int>& res, int pos) {
if (res.size() == 2) {
return;
}
for (int i = pos; i < 4; ++i) {
res.push_back(i);
DFS(res, i+1);
res.pop_back();
}
}
int main()
{
vector<int> res;
DFS(res, 0);
return 0;
}