递归是一种应用非常广泛的算法(或者编程技巧)。也是很多数据结构和算法编码实现的基础。比如DFS深度优先搜索、前中后序二叉树遍历等等,所以搞懂递归是学习后面复杂的数据结构和算法的前提条件。
1. 理解递归
递归在我们的生活中也是很常见的:
在电影院里,在漆黑的时候,我们没法直接知道自己是第几排,于是我们就可以问前一排的人他是第几排,我们只要在前一个人的基础加一,但前面一排的人也看不清楚,所以他也要问他前面的人。就这样一排一排往前问,直到问到第一排的人,因为第一排的人本身就知道自己是第一排,然后再这样一排一排的把数字传回来。直到你前面的人告诉你他在哪一排,于是就知道你自己是第几排了。
上面的例子是一个非常标准的递归求解问题的分解过程,去的过程叫“递”,回来的过程叫“归”。
递归问题几乎都可以用递推公式来表示。上面电影院的例子的是:
f(n)=f(n-1)+1 其中,f(1)=1
f(n)表示你想知道自己在哪一排,f(n-1)表示前面一排所在的排数,f(1)=1表示第一排的人知道自己在第一排。
根据上面的递推公式,我们就可以写出递推代码:
int f(int n) {
if (n == 1) return 1;
return f(n-1) + 1;
}
2. 递归需满足的三个条件
只有同时满足下面三个条件的问题,才能用递归来解决。
1. 一个问题的解可以分解为几个子问题的解
何为子问题?子问题就是数据规模更小的问题。比如前面电影院的例子,你要知道"自己在哪一排"的问题,可以分解为"前一排的人在哪一排"这样的子问题。
2. 这个问题与分解之后的子问题,除了数据规模不同,求解思路完全一样
比如电影院的例子,你求解"自己在哪一排"的思路,和前面一排人求解"自己在哪一排"的思路,是一模一样的。
3. 存在递归终止条件
把问题分解为子问题,再把子问题分解为子子问题,一层一层分解下去,不能存在无限循环,这就需要有终止条件。