简体   繁体   English

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

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

Theres an exercise from a Java book I'm reading that has me confused: 我正在阅读的一本Java书籍中有一个练习让我感到困惑:

A Fibonacci sequence is the sequence of numbers 1, 1, 2, 3, 5, 8, 13, 21, 34, etc., where each number (from the third on) is the sum of the previous two. 斐波那契数列是数字1、1、2、3、5、8、13、21、34等的序列,其中每个数字(从第三个数字开始)是前两个数字的和。 Create a method that takes an integer as an argument and displays that many Fibonacci numbers starting from the beginning. 创建一个以整数作为参数并从头开始显示许多斐波那契数的方法。 If, eg, you run java Fibonacci 5 (where Fibonacci is the name of the class) the output will be: 1, 1, 2, 3, 5. 例如,如果您运行Java Fibonacci 5(其中Fibonacci是类的名称),则输出将为:1、1、2、3、5。

I could have swore that it would need an array or some way of storing the previous numbers but when I saw the answer it wasn't the case: 我可能会发誓,它需要一个数组或某种方式来存储先前的数字,但是当我看到答案时,情况并非如此:

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) + ", ");
    }
}

Would someone be able to explain how using a function within itself produces this? 有人能够解释一下如何在自身内部使用函数吗?

The code you gave is an example of a recursive solution. 您提供的代码是递归解决方案的示例。 When the function is called for the first time, it executes until it calls itself. 首次调用该函数时,它将执行直到调用自身。 Its state is stored on the stack, and the code begins executing again with new input data. 它的状态存储在堆栈中,并且代码开始使用新的输入数据再次执行。 This process repeats until the input is less than 2, at which point 1 is returned, and the answer returns to the previous caller. 重复此过程,直到输入小于2,然后返回1,然后答案返回到先前的呼叫者。

For example, calling fib(5) results in the following execution: 例如,调用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

Note that you are partially correct. 请注意,您部分正确。 Intermediate results are stored on the stack in this solution. 中间结果在此解决方案中存储在堆栈中。 That is one of the reasons why the recursive solution is so expensive. 这就是递归解决方案如此昂贵的原因之一。 The other is its O(2^n) complexity. 另一个是它的O(2^n)复杂度。 However, if is possible to compute Fibonacci(n) iteratively and without storing all previous results. 但是,如果可以迭代地计算Fibonacci(n) ,而无需存储所有先前的结果。 All you really need is to store the last to results and count from 1 up to 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)

Important point to note is this algorithm is exponential because it does not store the result of previous calculated numbers. 需要注意的重要一点是该算法是指数算法,因为它不存储先前计算得出的数字的结果。 eg F(n-3) is called 3 times. 例如F(n-3)被调用3次。

For more details refer algorithm by dasgupta chapter 0.2 有关更多详细信息,请参阅dasgupta的算法第0.2章

This is a recursive solution. 这是一个递归解决方案。 A recursive function calls itself until a given stop condition is met. 递归函数将自行调用,直到满足给定的停止条件为止。 Then each call exits until only the first call remains. 然后,每个呼叫都退出,直到仅剩下第一个呼叫为止。 That first call outputs the result. 第一个调用输出结果。

In your solution, the stop condition is : 在您的解决方案中,停止条件为:

if (n <= 2) 
          return 1;

until this condition is met, the function will make successive calls to itself. 在满足此条件之前,该函数将对其自身进行连续调用。 Each call reduces the int passed as a parameter. 每次调用都会减少作为参数传递的int值。 When it reaches 2, the stop condition dictates that the function returns with value 1 (the result of n=1 and n=2 in fibonacci(n) ). 当它达到2时,停止条件指示该函数返回值1(fibonacci(n)中n = 1和n = 2的结果)。

Because the fibonacci is the sum of the last two numbers, the recursive part of the function, 因为斐波那契数是最后两个数字的和,所以函数的递归部分

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

does a sum of n-1 and n-2 (as I said, the two last numbers of the sequence). 进行n-1和n-2的和(如我所说,序列的最后两个数字)。 When the n equals 2, these calls to function fib will finally have a value, and will be returned. 当n等于2时,这些对函数fib的调用最终将有一个值,并将被返回。

Example, if n = 3, the recursive part will call fib(2) and fib(1), both are equal or less than 2, so both calls will return 1. So the printf will print 1, 1, 2. 2 is the sum of 1 + 1 (I know it's obvious, but sometimes stating the obvious helps). 例如,如果n = 3,则递归部分将调用fib(2)和fib(1),它们都等于或小于2,因此这两个调用都将返回1。因此printf将输出1、1、2、2。 1 + 1的总和(我知道这很明显,但有时会说出明显的帮助)。

This is the standard example for an recursive function . 这是递归函数的标准示例。

The Fibonacci Numbers are declared recursive, too. 斐波那契数也被声明为递归的。

Both fib(1) and fib(2) are declared as 1. All others are calculated by adding the last two fibonacci numbers, so fib(3)=fib(2)+fib(1) . fib(1)fib(2)都声明为1。所有其他值都是通过将最后两个fibonacci数相加得出的,因此fib(3)=fib(2)+fib(1)

Compare this to the calculation method which does exactly this: 将此与执行此操作的计算方法进行比较:

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

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

By the way, this is a very slow way to calculate the fibonacci numbers, using two variables (you don't need all of them for the last one, only the last two!) and a loop is in O(n), the recursive function above has O(2^n) operations. 顺便说一句,这是使用两个变量来计算斐波那契数的一种非常慢的方法(您不需要为最后一个变量而只需要最后两个变量就使用所有变量!),并且循环在O(n)中进行,上面的递归函数具有O(2 ^ n)个运算。

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

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