[英]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的總和(我知道這很明顯,但有時會說出明顯的幫助)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.