數(shù)據(jù)結(jié)構(gòu)之理解遞歸

理解遞歸

要理解遞歸, 首先要理解遞歸 --佚名

遞歸是一種解決問題的方法, 他從解決問題的各個(gè)小部分開始, 知道解決最初的大問題. 遞歸通常涉及函數(shù)調(diào)用自身

// 能夠直接調(diào)用自身的方法或函數(shù)
function recursiveFunction(someParam) {
  recursiveFunction(someParams);
}

// 間接調(diào)用自身的函數(shù)
function recursiveFunction1(someParam) {
  recursiveFunction2(someParam);
}
function recursiveFunction2(someParam) {
  recursiveFunction1(someParam);
}

上面的兩個(gè)示例如果執(zhí)行會(huì)一直調(diào)用下去, 因此, 每個(gè)遞歸都必須有基線條件, 一個(gè)不再遞歸調(diào)用的條件(停止點(diǎn)), 以防止無(wú)限遞歸

計(jì)算一個(gè)數(shù)的階乘

數(shù) n 的階乘荐开,定義為 n!供炎,表示從 1 到 n 的整數(shù)的乘積, 5 的階乘表示為 5!,和 5 × 4 × 3 × 2 × 1 相等,結(jié)果是 120

  1. 迭代階乘
const factorialIterative = (number) => {
  if (number < 0) return undefined;
  let total = 1;
  for (let n = number; n > 1; n--) {
    total = total * n;
  }
  return total;
};

console.log("factorialIterative(5)", factorialIterative(5)); // 120
  1. 遞歸階乘
    • 5 的階乘 5*4*3*2*1
    • f(5) = 5 _ f(4): 我們可以用 5 _ 4! 來(lái)計(jì)算 5!
    • f(5) = 5 _ (4 _ f(3)): 需要計(jì)算 4!, 可以用 4 * 3!
    • f(5) = 5 _ 4 _ (3 * f(2))
    • f(5) = 5 _ 4 _ 3 _ (2 _ f(1))
    • f(5) = 5 _ 4 _ 3 _ 2 _ (1)
    • f(1)或 f(0) 返回 1, 1! = 1
const factorial = (n) => {
  if (n === 1 || n === 0) return 1; // 基線條件
  return n * factorial(n - 1);
};

console.log("factorial(5)", factorial(5));
調(diào)用棧
  1. JavaScript 調(diào)用棧大小的限制

如果忘記加上用以停止函數(shù)遞歸調(diào)用的基線條件左胞,會(huì)發(fā)生什么呢?遞歸并不會(huì)無(wú)限地執(zhí)行下去乔煞,瀏覽器會(huì)拋出錯(cuò)誤啸罢,也就是所謂的棧溢出錯(cuò)誤 (stack overflow error)

斐波那契數(shù)列

斐波那契數(shù)列是另一個(gè)可以用遞歸解決的問題。它是一個(gè)由 0加勤、1仙辟、1同波、2、3叠国、5未檩、8、13粟焊、21冤狡、34 等數(shù)組成的序列。數(shù) 2 由 1 + 1 得到项棠,數(shù) 3 由 1 + 2 得到悲雳,數(shù) 5 由 2 + 3 得到,以此類推

  • 位置 0 的 斐波那契數(shù)是零
  • 1 和 2 的斐波那契數(shù)是 1
  • n (此處 n > 2)的斐波那契數(shù)是(n - 1) 的斐波那契數(shù)加上(n - 2)的斐波那契數(shù)
  1. 迭代求斐波那契數(shù)
const fibonacciIterative = (n) => {
  if (n < 1) return 0;
  if (n <= 2) return 1;

  let fibNMinus2 = 0;
  let fibNMinus1 = 1;
  let fibN = n;

  for (let i = 2; i <= n; i++) {
    // n >= 2
    fibN = fibNMinus1 + fibNMinus2; // f(n-1) + f(n-2)
    fibNMinus2 = fibNMinus1;
    fibNMinus1 = fibN;
  }
  return fibN;
};

console.log("fibonacciIterative(10)", fibonacciIterative(10)); // 55
  1. 遞歸求斐波那契數(shù)
const fibonacci = (n) => {
  if (n < 1) return 0;
  if (n <= 2) return 1;
  return fibonacci(n - 1) + fibonacci(n - 2);
};

console.log("fibonacciIterative(10)", fibonacciIterative(10)); // 55
斐波那契
  1. 記憶化斐波那契數(shù)

記憶化是一種保存前一個(gè)結(jié)果的值的優(yōu)化技術(shù)香追,類似于緩存, 在上圖中, 我們可以看到 f(3) 被計(jì)算了兩次

// 聲明了一個(gè) memo 數(shù)組來(lái)緩存所有的計(jì)算結(jié)果
const fibonacci = ((memory = [0, 1]) => {
  return function fib(n) {
    let result = memory[n];

    if (typeof result !== "number") {
      result = fib(n - 1) + fib(n - 2);
      memory[n] = result;
    }

    return result;
  };
})();

console.log("fibonacci(10)", fibonacci(10));
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末合瓢,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子透典,更是在濱河造成了極大的恐慌晴楔,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,331評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件峭咒,死亡現(xiàn)場(chǎng)離奇詭異税弃,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)凑队,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門则果,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人顽决,你說我怎么就攤上這事〉枷唬” “怎么了才菠?”我有些...
    開封第一講書人閱讀 167,755評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)贡定。 經(jīng)常有香客問我赋访,道長(zhǎng),這世上最難降的妖魔是什么缓待? 我笑而不...
    開封第一講書人閱讀 59,528評(píng)論 1 296
  • 正文 為了忘掉前任蚓耽,我火速辦了婚禮,結(jié)果婚禮上旋炒,老公的妹妹穿的比我還像新娘步悠。我一直安慰自己,他們只是感情好瘫镇,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,526評(píng)論 6 397
  • 文/花漫 我一把揭開白布鼎兽。 她就那樣靜靜地躺著答姥,像睡著了一般。 火紅的嫁衣襯著肌膚如雪谚咬。 梳的紋絲不亂的頭發(fā)上鹦付,一...
    開封第一講書人閱讀 52,166評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音择卦,去河邊找鬼敲长。 笑死,一個(gè)胖子當(dāng)著我的面吹牛秉继,可吹牛的內(nèi)容都是我干的祈噪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,768評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼秕噪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼钳降!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起腌巾,我...
    開封第一講書人閱讀 39,664評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤遂填,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后澈蝙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吓坚,經(jīng)...
    沈念sama閱讀 46,205評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,290評(píng)論 3 340
  • 正文 我和宋清朗相戀三年灯荧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了礁击。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,435評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逗载,死狀恐怖哆窿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情厉斟,我是刑警寧澤挚躯,帶...
    沈念sama閱讀 36,126評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站擦秽,受9級(jí)特大地震影響码荔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜感挥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,804評(píng)論 3 333
  • 文/蒙蒙 一缩搅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧触幼,春花似錦硼瓣、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,276評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)噪猾。三九已至,卻和暖如春筑累,著一層夾襖步出監(jiān)牢的瞬間袱蜡,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工慢宗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坪蚁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,818評(píng)論 3 376
  • 正文 我出身青樓镜沽,卻偏偏與公主長(zhǎng)得像敏晤,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子缅茉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,442評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容