JS 從斐波那契數列淺談遞歸

1、前言算法

昨晚下班後,經理出於興趣給咱們技術組講了講算法相關的東西,全程一臉懵逼的聽,中途還給咱們出了一道比較有趣的爬樓問題,問題以下:閉包

假設一我的從地面開始爬樓梯,規定一步只能爬一坎或者兩坎,人只能往上走,例如爬到第一坎,很明顯從地面到第一坎只有一種可選方式,從地面爬到第二坎,他能夠從地面直接跨到第二坎,也能夠先從地面到第一坎,再從第一坎到第二坎,也就是2種可選方式,那麼求他爬到N樓一共有幾種可選方式。函數

這道題涉及到了斐波那契數列,要求使用遞歸來求值,技術賊菜的我也是一臉懵逼,因此本着學習的心仍是記錄下來了。學習

2、有趣的斐波那契數列spa

咱們將地面理解爲數字0,第一坎理解爲數字1,以此來進行簡單的分析:3d

例如從0到1,就一種選擇,如圖(公司不讓用破解軟件,沒PS畫圖,湊合看吧,畫圖的手微微顫抖。。。)code

那麼,如今要求到第二坎,從0到2呢,兩種選擇,看圖分析(記住,一步只能跨一坎或者兩坎):blog

當要求從0到3,三種選擇,如圖:遞歸

紫色:一坎坎的走;黃色:先走兩坎,再走一坎;藍色:先走一坎,再走兩坎。ci

從0-4,一共五種狀況,如圖:

這裏我分開畫了,左邊的2種狀況加上右邊的三種狀況

左邊:

第一種:一坎坎的走,0-1-2-3-4

第二種:兩坎兩坎走,0-2-4

右邊:

第三種:先走兩坎,再一坎坎的走0-2-3-4

第四種:先走一坎,再走兩坎,再走一坎0-1-3-4

第五種:先走一坎,再走一坎,再走兩坎0-1-2-4

當咱們繼續日後畫,樓梯層對應走法會造成一個有趣的規律,

從第三層開始,第三層的走法等於一層與二層走法的和,第四層的走法等於第二層和第三層走法的和.....針對樓梯問題,咱們能夠獲得以下公式:

F(n) = F(n-1) + F(n-2)   n>=3

這就是著名的斐波那契數列(Fibonacci sequence),又稱黃金分割數列。有興趣的同窗能夠查查兔子繁殖問題。

百科裏斐波那契數列的基數n>=4是根據實際狀況來定的,這點不用糾結。

3、斐波那契數列與遞歸的結合

什麼是遞歸?本身調用本身的函數就是遞歸,這麼說徹底沒問題。

咱們迴歸上面的問題,要求第N層的走法,那咱們只須要知道N-1層和N-2層的走法就行了,假設N是10,求到第十層的走法。

十層走法=九層的走法+八層走法

九層和八層也能夠拆分啊,九層走法 = 七層走法 + 八層走法 ,而八層走法 = 七層走法 + 六層走法

.......

當分到3層時,最後還能夠拆分爲1層+2層,由於規律是從第三層開始的,由於此公式不適用於1層和2層,分到1層和2層就表明分支的結束了。

使用閉包須要找到跳出本身調用本身的的臨界條件,否則會會陷入死循環,那對應咱們的樓梯問題,只要N<3時就不須要繼續調用本身了,由於不須要繼續產生分支了。

這個閉包怎麼寫呢?咱們結合斐波那契數列公式嘗試一下吧。

如今有一個函數,裏面申明一個走法變量var step = 0;輸入一個數字N,咱們會對N判斷,只要N>=3,它就會本身調用本身,小於3時,咱們分別判斷它等於1或者2,等於1就讓step加1,等於2就讓step加2,以下:

function recursion(n){
    let step = 0;
    if (n === 1 ){
        step += 1
    }else if (n === 2){
        step += 2;
    }else if (n >= 3){
        step = recursion(n-1) + recursion(n-2);
    };
    return step;
};
console.log(recursion(10))//89種

爲了驗證,我將上方分支圖中全部的1與2相加(1層只有1種走法,2層有2種),得出數字也確實是89。因此我不明白我爲何要把基數N設置爲10,算的難受。

那麼趁熱打鐵,活學活用,如今咱們嘗試求正整數N與N以前全部正整數累加的和

例如3以前累加的和就是3+2+1,數字0加不加沒意義,因此跳出遞歸的臨界條件就是當N>=2時,最後調用一次讓以前數字的和加一次1就行了。

var result = 0;
function add(n){
    result += n
    n>=2 ? add(n-1) : null;
    return result;
};
console.log(add(10));//55

驗證一下,徹底沒問題,有沒有以爲遞歸挺簡單。

當你看到這時,恭喜你,不只瞭解了斐波那契數列,也簡單瞭解了遞歸的用法。其實本人在工做中須要操做數據,本能的老是想到窮舉,循環,那麼如今又多了一種可行的解決方法,也算是對於思惟的開拓了。

留個問題,回到上方兩段實現代碼,爲何第一個變量申明在函數體內,而第二個數字累加的變量申明要在函數體外呢?嘗試思考下。

固然,前提是,這篇博客若是有人願意看完就挺好了。

相關文章
相關標籤/搜索