LeetCode.509——斐波那契數


  • 問題描述:

    斐波那契數,一般用 F(n) 表示,造成的序列稱爲斐波那契數列。該數列由 0 和 1 開始,後面的每一項數字都是前面兩項數字的和。也就是:java

    F(0) = 0,   F(1) = 1
    F(N) = F(N - 1) + F(N - 2), 其中 N > 1.

    給定 N,計算 F(N)。算法

    示例 :數組

    輸入:2
    輸出:1
    解釋:F(2) = F(1) + F(0) = 1 + 0 = 1.
  • 問題分析:

    因爲計算任何一個第n(n >= 2)項的數都須要知道其前面兩個數,即須要知道n-1和n-2是多少,而後兩個相加獲得結果,可是問題來了,要知道n-1,就要須要知道n-2,要知道n-2就須要知道n-3,會一直這樣的循環遞歸下去,一直到第一個數,第二個,第三個.......再反推回來。 那就很明顯了,你們第一時間想到的方法即是遞歸,就下來實現一下:code

    方法一:遞歸實現blog

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

​ 問題分析:遞歸

​ 先看一下遞歸圖:內存

​ 因爲不少數的計算都要重複不少次,效率並不高,時間複雜度達到了 O(2^n),是斐波那契數計算中 時間複雜度最大,最不可取的方法。io

​ 空間複雜度:O(n),堆棧中須要的空間與 N 成正比,堆棧會跟蹤 fib(n) 的調用,隨着堆棧的不斷增加 若是沒有足夠的內存則會出現StackOverflowError異常。class

​ 注:定義爲int型時,最大隻能求到n = 46,f(46) = 1836311903, 而 f(47) = -1323752223,由於超出了int 型數值的最大範圍。效率

  • 算法改進:

    使用遞歸的同時,使用記憶化方式存儲已經計算過的數據,減小沒必要要的重複計算,可使時間複雜度降到 O(N),同時空間複雜度也是O(N)。具體的實現是使用一個數組,把每次計算過的值都存儲進去,當再次使用這個數的時候,直接返回,不須要再進行遞歸。

    方法二:記憶化自底向上遞歸

    public class Solution {
       public int fib(int n) {
          if(n <= 1){
                return n;
            }
             int[] memo = new int[n+1];
             memo[1] = 1;
             for(int i = 2;i <= n; i++){
                 //自底向上填充數組,一直到須要的那個數
                 memo[i] = memo[i-1] + memo[i-2];
             }
             return memo[n];
         }
    }

  • 最後:

    限於水平有限,斐波那契數的實現還有不少種方法,不能一一列舉,當其中大部分都有相似的思想。

    水文中若有不許確或是錯誤之處,還望指出。謝謝~~~

    下一篇:LeetCode.62——不一樣路徑

相關文章
相關標籤/搜索