【刷演算法】我知道的所有類似斐波那契數列的問題

亞古發表於2018-06-20

有一類演算法問題類似斐波那契數列,而且解決辦法基本差不多。

跳臺階問題

題目描述

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

分析

設到第n階總共有f(n)種跳法,而且想跳到第n階只有兩種可能,要麼從第n-1階跳一階到達,要麼從第n-2階跳兩階到達,所以遞推式為f(n)=f(n-1)+f(n-2)。特殊情況為,n=0的時候跳法為0;n=1時,跳法為1;n=2時,跳法為2

遞迴

function jump(n) {
    if(n < 1)
        return 0;
    if(n === 1)
        return 1;
    if(n === 2)
        return 2;
    return jump(n-1) + jump(n-2);
}
複製程式碼

非遞迴

function jumpFloor(number)
{
    if(number < 1)   
        return 0;
    if(number === 1)
        return 1;
    if(number === 2)
        return 2;
    var s1 = 1;
    var s2 = 2;
    var res =  0;
    for(var i = 3;i <= number;i++){
        res = s1 + s2;
        s1 = s2;
        s2 = res;
    }
    return res;
}
複製程式碼

變態跳臺階問題

題目描述

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

分析

變態的跳臺階問題處理起來確實是有些棘手,一次可以跳上的階數是不定的。
先看n=0時,跳法f(0)=0;
n=1,只能是從第0個臺階跳過來,跳法f(1)=1;
n=2,可能是第0個臺階跳了2階或者從第1個臺階跳了1階,跳法f(2)=f(0)+f(1);
n=3,可能是第0個臺階跳了3階、第1個臺階跳了2階、第2個臺階跳了1階,跳法f(3)=f(0)+f(1)+f(2);
...
n=n-1,跳法f(n-1)=f(0)+f(1)+f(2)+...+f(n-2);
n=n,跳法f(n)=f(0)+f(1)+f(2)+...+f(n-1);
由上面兩個等式得:f(n) = f(n-1)+f(n-1) = 2f(n-1)
程式碼實現:

function jumpFloorII(number)
{
    if(number < 1)
        return 0;
    if(number === 1)
        return  1;
    return 2*jumpFloorII(number-1)
}
複製程式碼

矩陣覆蓋

題目描述

我們可以用21的小矩形橫著或者豎著去覆蓋更大的矩形。請問用n個21的小矩形無重疊地覆蓋一個2*n的大矩形,總共有多少種方法?

分析

ps:為了方便分析問題,給每個小矩形不同的顏色,其實他們之間沒有差別

【刷演算法】我知道的所有類似斐波那契數列的問題
假設上圖為用n個21的小矩形無重疊地覆蓋一個2n的大矩形,方法數為f(n),那麼f(n)可以從哪些情況推匯出來呢? 首先很明顯我們知道,2*1的小矩形要麼是橫著放要麼是豎著放,所以f(n)的情況只能由以下兩種情況得來:

【刷演算法】我知道的所有類似斐波那契數列的問題
這種情況只需要再加一個豎著的小矩形就可以了,所以這種情況其實是f(n-1)

【刷演算法】我知道的所有類似斐波那契數列的問題
這種情況下,只需要再加一個橫著的小矩形就可以了,但是由於這種橫著的小矩形只能成對出現,所以這種情況其實是f(n-2)
綜上,f(n) = f(n-1)+f(n-2)
特殊情況時,f(0)=0,f(1)=1,f(2)=2

遞迴

function rectCover(n)
{
    if(n === 0)
        return 0;
    if(n === 1)
        return 1;
    if(n === 2)
        return 2;
    return rectCover(n-1) + rectCover(n-2)
}
複製程式碼

非遞迴

function rectCover(n)
{
    if(n === 0)
        return 0;
    if(n === 1)
        return 1;
    if(n === 2)
        return 2;
    var s1 = 1, s2 = 2;
    var res = 0;
    for(var i = 3;i <= n;i++) {
        res = s1 + s2;
        s1 = s2;
        s2 = res;
    }
    
    return res;
}
複製程式碼

母牛生小牛問題

題目描述

假設農場中成熟的母牛每年只會生一頭小母牛,且永遠不會死。第一年農場有1頭成熟的母牛,從第二年開始,母牛開始生小母牛,每隻小母牛3年之後成熟又可以生小母牛。給定整數N,求N年後牛的數量。

分析

設f(n)為n年後牛的數量,則第n年牛的來源有兩個。
首先,牛是永遠不會死的,所以第n-1的牛都會活到第n年;
其次,還有一部分新生的牛,因為每隻小母牛3年之後成熟才可以生小母牛,所以第n-3年的未成熟小母牛到了第n年會成熟且開始生小母牛,所以第n年新生的牛來自於第n-3年的未成熟小母牛和成熟母牛。
綜上,f(n) = f(n-1) + f(n-3)
特殊的,f(1)=1,f(2)=2,f(3)=3

直接非遞迴版

function cow(n) {
    if(n < 1)
        return 0;
    if(n === 1)
        return 1;
    if(n === 2) 
        return 2;
    if(n === 3)
        return 3;
    var s1 = 1, s2 = 2, s3 = 3;
    var res = 0;
    for(var i = 4;i <= n;i++){
        res = s1+s3;
        s1 = s2;
        s2 = s3;
        s3 = res;
    }
    
    return res;
}
複製程式碼

相關文章