《劍指offer》Java學習錄:面試題9:斐波那契數列

面試題 9:斐波那契數列

題目:

寫一個函數,輸入n,求斐波那契(Fibonacci)數列的第n項。斐波那契數列的定義如下:
f(n)={0,n=01,n=1f(n1)+f(n2),n>1 f(n)= \begin{cases} 0, & \text{$n = 0$}\\ 1, & \text{$n = 1$}\\ f(n - 1) + f(n - 2),& \text{$n > 1$} \end{cases}

分析

首先想到的是利用遞歸來解,如:

public static int fibonacci(int n) {
    if (n <=0 ) {
        return 0;
    } else if (n == 1) {
        return 1;
    } else {
        return fibonacci(n - 1) + fibonacci(n - 2);
    }
}

該解法確實簡單,很快就可以實現。讓我們來分析一下:

我們以求解f(10)f(10)爲例分析求解過程。想要求f(10)f(10)就的求f(9)f(9)f(8)f(8),想要求f(9)f(9)需要先求f(8)f(8)f(7)f(7),同樣想要求f(8)f(8),又得先求f(7)f(7)f(6)f(6) … 我們可以以樹結構表達這種依賴關係。
在這裏插入圖片描述
不難發現,書中有很多節點重複,這意味着計算量會隨着n的增大而急劇增大,事實上,用遞歸計算的時間複雜度是以n的指數遞增的。我試了一下,當n爲45時,就能很明顯的發現獲得結果需要等待一小會兒了。

改進

上面遞歸代碼之所以慢是因爲重複計算過多,當我們的遞歸從小往大計算時,第n次的結果總是前兩次之後,而前兩次剛好再前面兩次已經計算過並記錄了。

public static void main(String args[]) {
    System.out.println(fibonacci1(1000));
}

public static int fibonacci1(int n) {
    int[] result = {0, 1};
    if (n < 2) {
        return result[n];
    }
    int preNumberOne = 1;
    int preNumberTwo = 0;
    int number = 0;
    for (int i = 2; i <= n; i++) {
        number = preNumberOne + preNumberTwo;
        preNumberTwo = preNumberOne;
        preNumberOne = number;
    }
    return number;
}

斐波那契數列的運用:青蛙跳臺階

題目

一隻青蛙可以跳上1級臺階,也可以跳上2級臺階。求該青蛙跳上一個n級臺階總共有多少種跳法。

分析

首先考慮最簡單的情況,如果只有一級臺階,青蛙第一次跳的時候,顯然只有一種跳法。如果有2級,有兩種跳法:一種是跳一級、一種是跳兩級。

再看一般情況,假如青蛙跳n級臺階總共有F(n)F{(n)} 種跳法,當n > 2 時,第一次有兩種不同的選擇:1. 只跳1級,此時跳法數據等於後面剩下的n - 1級臺階的跳法數目,即 $ F(n - 1)2.2n2。2. 只跳2級,此時跳法數目等於後面剩下的n - 2級臺階的跳法數目,即 F(n - 2)$ 。因此n級臺階的不同跳法總數爲F(n)=F(n1)+F(n2)F(n) = F(n - 1) + F(n - 2)。不難看出,這就是一個斐波那契數列。

斐波那契數列的運用:矩形覆蓋

題目

我們可以用2 x 1的小矩形橫着或者豎着去覆蓋更大的矩形。請問用8個 2 x 1的小矩形無重疊地覆蓋一個 2 x 8的大巨星,總共有多少種方法?矩形如圖:

fugai
在這裏插入圖片描述

分析

先把2 x 8的覆蓋方法次數記爲F(8)F(8) , 用1x2的矩形第一次覆蓋到2x8上有兩種方式:

  1. 豎着蓋在最左邊,此時的覆蓋次數有F(7)F(7)
  2. 橫着覆蓋最左上角, 此時覆蓋次數記爲F(6)F(6)
  3. 所以,對於2x8的矩形區域,F(8)=F(7)+F(6)F(8) = F(7) + F(6)

顯然,又是一個斐波那契數列。

結語

斐波那契數列相關題目特徵:

  1. 每個步驟有兩種不同的操作。
  2. 有0和1兩個解。
  3. 經過兩個不同操作後,問題規模將會得到不同程度的降低。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章