如何理解“递归”?
在数学与计算机科学中,递归 (Recursion))是指在函数的定义中使用函数自身的方法,直观上来看,就是某个函数自己调用自己。
咱们生活中就有很多用到递归的例子。周末你带着女朋友去电影院看电影,女朋友问你,咱们现在坐在第几排啊?电影院里面太黑了,看不清,没法数,现在你怎么办?递归就开始排上用场了。于是你就问前面一排的人他是第几排,你想只要在他的数字上加一,就知道自己在哪一排了。但是,前面的人也看不清啊,所以他也问他前面的人。就这样一排一排往前问,直到问到第一排的人,说我在第一排,然后再这样一排一排再把数字传回来。直到你前面的人告诉你他在哪一排,于是你就知道答案了。
这就是一个非常标准的递归求解问题的分解过程,去的过程叫“递”,回来的过程叫“归”。基本上,所有的递归问题都可以用递推公式来表示。刚刚这个生活中的例子,我们用递推公式将它表示出来就是这样的:
递归有两层含义:
-
递归问题必须可以分解为若干个规模较小、与原问题形式相同的子问题。并且这些子问题可以用完全相同的解题思路来解决;
-
递归问题的演化过程是一个对原问题从大到小进行拆解的过程,并且会有一个明确的终点(临界点)。一旦原问题到达了这个临界点,就不用再往更小的问题上拆解了。最后,从这个临界点开始,把小问题的答案按照原路返回,原问题便得以解决。
简而言之,递归的基本思想就是把规模大的问题转化为规模小的相同的子问题来解决。 在函数实现时,因为大问题和小问题是一样的问题,因此大问题的解决方法和小问题的解决方法也是同一个方法。这就产生了函数调用它自身的情况,这也正是递归的定义所在。
格外重要的是,这个解决问题的函数必须有明确的结束条件,否则就会导致无限递归的情况。总结起来,递归的实现包含了两个部分,一个是递归主体,另一个是终止条件。
递归的应用
斐波拉契数列
斐波那契数列是:1,1,2,3,5,8,13,21,34,55,89,144……。你会发现,这个数列中元素的性质是,某个数等于它前面两个数的和;也就是 f[n] = f[n-1] + f[n-2]。至于起始两个元素,则分别为1 和 1。在这个数列中的数字,就被称为斐波那契数。
现在的问题是,写一个函数,输入 x,输出斐波那契数列中第 x 位的元素。例如,输入 4,输出3;输入 9,输出 34。要求:需要用递归的方式来实现。
/**
* 递归
*/
public class RecursionTest {
@Test
public void test() {
System.out.println(fibonacciSequence