劍指offer-斐波那契數列

題目描述

大家都知道斐波那契數列,現在要求輸入一個整數n,請你輸出斐波那契數列的第n項。

n<=39


這個題可以說是迭代(Iteration) VS 遞歸(Recursion),f(n) = f(n-1) + f(n-2),第一眼看就是遞歸啊,簡直完美的遞歸環境,遞歸肯定很爽,這樣想着關鍵代碼兩三行就搞定了,注意這題的n是從0開始的:
1
2
if(n<=1) return n;
else return Fibonacci(n-1)+Fibonacci(n-2);
然而並沒有什麼用,測試用例裏肯定準備着一個超大的n來讓Stack Overflow,爲什麼會溢出?因爲重複計算,而且重複的情況還很嚴重,舉個小點的例子,n=4,看看程序怎麼跑的:
Fibonacci(4) = Fibonacci(3) + Fibonacci(2);
                    = Fibonacci(2) + Fibonacci(1) + Fibonacci(1) + Fibonacci(0);
                    = Fibonacci(1) + Fibonacci(0) + Fibonacci(1) + Fibonacci(1) + Fibonacci(0);
由於我們的代碼並沒有記錄Fibonacci(1)和Fibonacci(0)的結果,對於程序來說它每次遞歸都是未知的,因此光是n=4時f(1)就重複計算了3次之多。
那麼如何求解呢,動態規劃似乎不錯,關於動態規劃三個條件:最優子結構、無後效性、子問題重疊。如果使用遞歸求解呢,那麼會重複計算一些子問題。例如,求f(10)需要計算f(9)和f(8),計算髮f(9)就要計算f(8)和f(7),可以看到f(8)被重複計算了。



遞歸方法是將一個問題劃分爲多個子問題求解,動態規劃也是如此,但是動態規劃會把子問題緩存起來,避免重複求解子問題。

public class Solution {
    private int[] fib = new int[40];
    public Solution() {
        fib[1] = 1;
        fib[2] = 2;
        for(int i = 2; i < fib.length; i++) {
            fib[i] = fib[i - 1] + fib[i - 2];
        }
    }
    public int Fibonacci(int n) {
        return fib[n];
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章