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
驗證一下,徹底沒問題,有沒有以爲遞歸挺簡單。
當你看到這時,恭喜你,不只瞭解了斐波那契數列,也簡單瞭解了遞歸的用法。其實本人在工做中須要操做數據,本能的老是想到窮舉,循環,那麼如今又多了一種可行的解決方法,也算是對於思惟的開拓了。
留個問題,回到上方兩段實現代碼,爲何第一個變量申明在函數體內,而第二個數字累加的變量申明要在函數體外呢?嘗試思考下。
固然,前提是,這篇博客若是有人願意看完就挺好了。