繁体   English   中英

Fibonacci(n)的这种实现方式如何工作? [递归]

[英]How does this implementation of Fibonacci(n) work? [recursion]

我正在阅读的一本Java书籍中有一个练习让我感到困惑:

斐波那契数列是数字1、1、2、3、5、8、13、21、34等的序列,其中每个数字(从第三个数字开始)是前两个数字的和。 创建一个以整数作为参数并从头开始显示许多斐波那契数的方法。 例如,如果您运行Java Fibonacci 5(其中Fibonacci是类的名称),则输出将为:1、1、2、3、5。

我可能会发誓,它需要一个数组或某种方式来存储先前的数字,但是当我看到答案时,情况并非如此:

import java.util.*; 

public class Fibonacci { 

    static int fib(int n) {
         if (n <= 2) 
              return 1;

         return fib(n-1) + fib(n-2);
    } 
    public static void main(String[] args) {
    // Get the max value from the command line: 
    int n = Integer.parseInt(args[0]); 
    if(n < 0) {
        System.out.println("Cannot use negative numbers"); return;
    } 
    for(int i = 1; i <= n; i++)
        System.out.print(fib(i) + ", ");
    }
}

有人能够解释一下如何在自身内部使用函数吗?

您提供的代码是递归解决方案的示例。 首次调用该函数时,它将执行直到调用自身。 它的状态存储在堆栈中,并且代码开始使用新的输入数据再次执行。 重复此过程,直到输入小于2,然后返回1,然后答案返回到先前的呼叫者。

例如,调用fib(5)将导致以下执行:

fib(5):
    fib(4):
        fib(3):
            fib(2): 1
            fib(1): 1
        fib(2): 1
    fib(3):
        fib(2): 1
        fib(1): 1

请注意,您部分正确。 中间结果在此解决方案中存储在堆栈中。 这就是递归解决方案如此昂贵的原因之一。 另一个是它的O(2^n)复杂度。 但是,如果可以迭代地计算Fibonacci(n) ,而无需存储所有先前的结果。 您真正需要的只是存储最后一个结果,并从1到n计数。

                           F(n)
                            /    \
                        F(n-1)   F(n-2)
                        /   \     /      \
                    F(n-2) F(n-3) F(n-3)  F(n-4)
                   /    \
                 F(n-3) F(n-4)

需要注意的重要一点是该算法是指数算法,因为它不存储先前计算得出的数字的结果。 例如F(n-3)被调用3次。

有关更多详细信息,请参阅dasgupta的算法第0.2章

这是一个递归解决方案。 递归函数将自行调用,直到满足给定的停止条件为止。 然后,每个呼叫都退出,直到仅剩下第一个呼叫为止。 第一个调用输出结果。

在您的解决方案中,停止条件为:

if (n <= 2) 
          return 1;

在满足此条件之前,该函数将对其自身进行连续调用。 每次调用都会减少作为参数传递的int值。 当它达到2时,停止条件指示该函数返回值1(fibonacci(n)中n = 1和n = 2的结果)。

因为斐波那契数是最后两个数字的和,所以函数的递归部分

return fib(n-1) + fib(n-2);

进行n-1和n-2的和(如我所说,序列的最后两个数字)。 当n等于2时,这些对函数fib的调用最终将有一个值,并将被返回。

例如,如果n = 3,则递归部分将调用fib(2)和fib(1),它们都等于或小于2,因此这两个调用都将返回1。因此printf将输出1、1、2、2。 1 + 1的总和(我知道这很明显,但有时会说出明显的帮助)。

这是递归函数的标准示例。

斐波那契数也被声明为递归的。

fib(1)fib(2)都声明为1。所有其他值都是通过将最后两个fibonacci数相加得出的,因此fib(3)=fib(2)+fib(1)

将此与执行此操作的计算方法进行比较:

static int fib(int n) {
     if (n <= 2) 
          return 1;

     return fib(n-1) + fib(n-2);
} 

顺便说一句,这是使用两个变量来计算斐波那契数的一种非常慢的方法(您不需要为最后一个变量而只需要最后两个变量就使用所有变量!),并且循环在O(n)中进行,上面的递归函数具有O(2 ^ n)个运算。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM