簡體   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