适用场景
以下三个条件需同时满足:Ref
- 一个问题的解可以分解为几个子问题的解
- 子问题与原问题除了数据规模不一样,求解思路完全一样
- 存在递归终止条件
如何编写递归代码
两步走:
- 写出递推公式(大问题化小问题)
- 找到终止条件
注意事项
计算机擅长做重复的事情,但是人脑不是。如果看到递归,总是想着一层一层地递归展开,,然后再一层一层地返回,人脑很容易被绕进去。
对于递归代码,这种试图想清楚整个递和归的过程的做法,实际上是进入了一个思维误区。很多时候,我们理解起来比较费劲,主要原因是自己给自己制造了这种理解障碍。
正确的解决方式就是把问题A分解成子问题B、C、D,假设B、C、D已经解决,然后找出A与B、C、D之间的关系即可,不需要一层一层地往下思考子问题和子子问题,子子问题和子子子问题之间的关系。屏蔽掉递归细节,这样理解起来就简单多了。
附:不需要自己思考递归之间的层层调用是因为计算机中栈这种数据结构已经为我们解决了。
例题:蓝桥杯-六角填数
这个问题是一个图遍历算法,应用的是深度优先搜索算法。首先,遍历一遍整个图,然后对遍历过的每个节点设置一个值。遍历完成后,如果当前设置的值满足题意,则打印输出,结束程序,
伪代码描述:
void 设置当前node的值(value) {
if( 所有的结点都已经访问过了) {
if( 满足题意 ) {打印结果; return;}
else {return;}
}
if( value未被使用 ) {
当前node的值 = value;
value = visited;
给下一个node设置值(++value);
} else {
设置当前node的值(++value);
}
}