理解递归的运行模型(https://zhuanlan.zhihu.com/p/166173378)之后,就能根据递归函数的静态代码推算执行结果了。递归思维,是理解递归的基础上,用递归研究并解决问题的一般方法。
要解决问题,首先要明确问题的本质,并清晰明了地表示问题,设计递归函数解决问题,先设计函数首部,再按框架设计函数体:
设计的详细步骤如下:
1.设计函数首部,用有意义的标识符给函数命名,确定函数返回值类型,用函数的参数刻画待解决问题的数量特征及其关系本质,特别地,函数参数(即变量)描述问题的规模;最后描述函数的功能,要非常明确函数要完成的任务,对设计者来说,无论口头和书面,都能清晰地、准确无误地描述。2设计递归函数的函数体:
确定最小问题,即确定递归边界,直接解决最小问题;当问题规模较大时,以“所有比函数首部定义的问题规模小的问题都已获解决”为思考解决方案的根基,对问题进行分解,用递归调用解决分解出的小问题,用小问题的解构造出函数首部定义的原问题的解;或者把定义的问题转换成更小的问题,然后递归解决更小问题即可。递归的三要素:定义描述问题;研究并解决最小问题;用递归解决大问题。
用递归思维解决问题,我们不必关注如何处理及求解问题的详细过程和步骤,你甚至可以不知道计算解题过程就把问题给编程解决了。就像孙悟空懂规则,但不知道具体如何玩汉诺塔,可他居然完成了移动汉诺塔的目标(https://zhuanlan.zhihu.com/p/168684834)。
在一定的时间、空间限制下,人的体力有限,思维力也有限,递归思维对实践最有用的指导,就是把脑力集中于定义问题这个关键点上,不用去找解题的过程。定义(问题)即解决(问题),定义即解决! 定义即解决!! 定义即解决!!! 指规模更小的问题立即获得解决, 从而导致轻松解决函数本身定义的问题。递归思维,强调思维的着力点在问题的定义描述上;设计函数体,寻求解法时,大脑理应不断地涌现出能轻易解决的各种小问题,它们是构造原问题的解的基础。
让我们一起感悟。
例:输入正整数n,按升序输出1~n之间的所有整数。
我们用函数实现,定义函数void print1n(int n);它的任务是按升序输出1~n之间的所有整数。
#include
以上的程序框架是能编译成功的,在此基础上,我们思考如何确定递归边界,如何划分成小问题。
#include
下面以另一种方法实现:假设定义了函数void printStartTerminal(int s,int t);它的功能是输出s~t之间的整数。
#include
以上的程序能通过编译,在其基础上可以得到下面的多种实现方法。
#include
递归思维的重心在明确地定义问题,然后解决最小问题,分解问题。
如果您觉得输出1~n的问题没啥意思,或者说对递归的奥妙无感。继续阅读下面文章,你就会觉得有意思了。
递归思维指引的设计——插入排序、快速排序的全递归实现
如何运用递归思维解决问题——冒泡、选择、合并排序