劍指Offer題目9:斐波那契數列(Java)

面試題9:你們都知道斐波那契數列,如今要求輸入一個整數n,請你輸出斐波那契數列的第n項(從0開始,第0項爲0)。n<=39面試

Basic :斐波那契數列定義

當 0 < n <= 1 時,f(n) = n;
當 n > 1 時,f(n) = f(n-1) + f(n-2)
複製代碼

解題思路

1、遞歸寫法(低效,慢)bash

遞歸分析,以下圖所示:ui

這棵樹中有不少結點是重複的,並且重複的結點數會隨着n的增大而急劇增長,這意味計算量會隨着n的增大而急劇增大。spa

用遞歸方法計算的時間複雜度是以n的指數的方式遞增的。code

2、for 循環寫法cdn

使用中間變量,在每次循環以後都將中間計算結果保存起來,用於下一次循環,時間複雜度減小到O(n)。blog

代碼實現

1、遞歸寫法(低效,慢)遞歸

public class Solution {
    public int Fibonacci(int n) {
        if(n <= 1) {
            return n;
        }
        return Fibonacci(n-1) + Fibonacci(n-2);
    }
}
複製代碼

2、for 循環寫法ci

public class Solution {
    public int Fibonacci(int n) {
        if(n <= 1) {
            return n;
        }
        int fibNMinus1 = 1;
        int fibNMinus2 = 0;
        int fibN = 0;
        for(int i=2; i<=n; i++){
            fibN = fibNMinus1 + fibNMinus2;
            fibNMinus2 = fibNMinus1;
            fibNMinus1 = fibN;
        }
        return fibN;
    }
}
複製代碼

總結

遞歸實現起來簡潔,但一般效率比for循環要低不少。get

擴展:青蛙跳臺階

題目:一隻青蛙一次能夠跳上1級臺階,也能夠跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法(前後次序不一樣算不一樣的結果)。

思路分析

前提只有 一次 1階或者2階的跳法。

a.若是兩種跳法,1階或者2階,那麼假定第一次跳的是一階,那麼剩下的是n-1個臺階,跳法是f(n-1);

b.假定第一次跳的是2階,那麼剩下的是n-2個臺階,跳法是f(n-2)

c.由a和b 兩種假設能夠得出總跳法爲: f(n) = f(n-1) + f(n-2) 

d.Base case:只有一階的時候 f(1) = 1 ,只有兩階的時候能夠有 f(2) = 2
複製代碼
public class Solution {
    public int JumpFloor(int target) {
        if(target <= 0) {
            return -1;
        }
        if(target <= 2){
            return target;
        }
        return JumpFloor(target - 1) + JumpFloor(target - 2);
    }
}
複製代碼

題目:一隻青蛙一次能夠跳上1級臺階,也能夠跳上2級……它也能夠跳上n級。求該青蛙跳上一個n級的臺階總共有多少種跳法。

數學概括法,各類計算,略過。

題目:咱們能夠用2×1(圖2.13的左邊)的小矩形橫着或者豎着去覆蓋更大的矩形。請問用8個2×1的小矩形無重疊地覆蓋一個2×8的大矩形(圖2.13的右邊),總共有多少種方法?

思路分析

首先把 2x8 的覆蓋方法總數記爲 f(8)。

用第一個 1x2 小矩形去覆蓋大矩形的最左邊時有兩個情形,豎着放或者橫着放。

豎着放:右邊還剩下 2x7 的區域,這種情形下的覆蓋方法記爲 f(7)。

橫着放:1x2 小矩形無論是橫着放在左上角仍是左下角,另一個小矩形必須跟在該小矩形的下邊或上邊貼合,即不管如何只有
一種覆蓋方法。而此時右邊還剩下 2x6 的區域,這種情形下的覆蓋方法記爲 f(6)。

2x8 的覆蓋方法就由這兩種情形構成,所以,他們之間存在如下關係:

f(8) = f(7) + f(6)

類推:f(n) = f(n-1) + f(n-2) 即斐波那契數列。
複製代碼

代碼實現

public class Solution {
    public int RectCover(int target) {
        if(target<=2) {
            return target;
        }
        return RectCover(target - 1) + RectCover(target - 2);
    }
}
複製代碼
相關文章
相關標籤/搜索