1. 程式人生 > 實用技巧 >劍指offer_07:斐波那契數列

劍指offer_07:斐波那契數列

寫一個函式,輸入 n ,求斐波那契(Fibonacci)數列的第 n 項。斐波那契數列的定義如下:

F(0) = 0, F(1) = 1
F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
斐波那契數列由 0 和 1 開始,之後的斐波那契數就是由之前的兩數相加而得出。

答案需要取模 1e9+7(1000000007),如計算初始結果為:1000000008,請返回 1。

示例 1:
輸入:n = 2
輸出:1

示例 2:
輸入:n = 5
輸出:5

提示:
0 <= n <= 100

1、原始遞迴,超時

我在網上還看到一種遞迴解法,就是每次遞迴的時候額外帶一個輔助空間,遞迴時算出來的數存到輔助空間裡,下一次遞迴時還能用到,這種遞迴其實也算是一種動態規劃思想。

class Solution {
    public int fib(int n) {
        if(n<2){
            return n;
        }
        return (fib(n-1)+fib(n-2))%1000000007;
    }
}

2、動態規劃

哪些問題適用動態規劃:

  1. 有重疊子問題
  2. 具有最優子結構
  3. 無後效性:這個狀態之後的過程不會影響到這個已經用完的狀態

動態規劃解題步驟:

  1. 拆解問題並找到子問題之間聯絡
  2. 定義初始狀態
  3. 確定狀態轉移方程
  4. 確定邊界條件並實現
class Solution {
    public int fib(int n) {
        if(n<2) return n;
        int[] dp=new int[n+1];
        dp[0]=0;
        dp[1]=1;
        for(int i=2;i<=n;i++){
            dp[i]=(dp[i-1]+dp[i-2])%1000000007;
        }
        return dp[n];
    }
}

3、動態規劃優化

優化動態規劃一般是優化空間,依據公式dp[i]=dp[i-1]+dp[i-2],可知要計算的數只與前兩個數相關,所以可以不使用陣列,使用三個變數就行。

class Solution {
    public int fib(int n) {
        if(n<2) return n;
        int first=0;
        int second=1;
        for(int i=2;i<=n;i++){
            int sum=(first+second)%1000000007;
            first=second;
            second=sum;
        }
        return second;
    }
}