PHP面试一战到底
上QQ阅读APP看书,第一时间看更新

4.2 递归

4.2.1 递归的原理

递归是指函数直接或间接地重复调用自身的过程。在处理某些问题时,递归可以显著地降低难度,例如二叉树的前序、中序、后序遍历,汉诺塔问题等。

实质上,递归的原理类似于数学归纳法,证明分两个步骤:

(1)证明当n=1时命题成立。

(2)证明如果在n=m时命题成立,那么可以推导出在n=m+1时命题也成立。(m代表任意自然数)

递归处理问题也有两个基本要素:

● 起始条件或退出条件。

● 问题分解为子问题。

我们来看一个基础的阶乘的递归实现示例,程序代码如下:(源码文件:ch04/fact.php)

第4至6行是退出条件,即0!=1,1!=1。

第7行,将阶乘问题分解,即

fact(10) = 10* fact(9)
fact(9) = 9 * fact(8)
…
fact(2) = 2 * fact(1) = 2 * 1

依次调用即得到最后的结果。

4.2.2 递归的优缺点

1.递归的优点

● 将复杂问题分解为简单问题,易于理解。

● 实现简单,某些问题转换为迭代之后实现方极其复杂(如汉诺塔问题),但使用递归实现就要简单很多。

2.递归的缺点

● 函数调用次数多,效率低。

● 空间浪费较多。

● 可能存在多余的调用。

● 递归层级过深造成堆栈的溢出。

递归的优点和缺点,使得科学家们对其“又爱又恨”,为了扬长避短,科学家们利用动态规划缓解递归的某些缺点。关于动态规划的实现我们在第12章第7节将会详细描述。

4.2.3 面试题:用递归实现斐波那契数列

斐波那契数列(Fibonacci Sequence)的第1项和第2项为1,从第3项开始,每一项都是前两项之和:

1  1  2  3  5  8  13  21...

程序实现如下:(源码文件:ch04/fibonacci.php)

4.2.4 面试题:二叉树的中序遍历

题目描述:利用递归实现二叉树的中序遍历。

解答:二叉树的中序遍历,是按照左子树→根结点→右子树的顺序访问二叉树的所有结点。访问的操作包括操作结点的值、更改结点的值等。

示例代码如下:(源码文件:ch04/tree.php)