1. 程式人生 > >使用遞歸解決斐波那契數列的性能問題

使用遞歸解決斐波那契數列的性能問題

還需 都是 來看 次數 pan 當前 turn 提高 遞歸

原文:使用遞歸解決斐波那契數列的性能問題

我們知道斐波那契數列(也稱作兔子數列) 1,1,2,3,5,8,13,21,34。。。。。

前兩位數固定是1,之後每一位數都是前兩位數的之和,這樣的數列就是斐波那契數列

那麽我們要求這樣的數列,就必須要求n-1和n-2位數

    function getFB(n){
      if(n == 1 || n == 2){   
    // 這裏我們先保持前兩位數是1
return 1; }else { return getFB(n-1) + getFB(n-2); } } console.log(getFB(
10));

求斐波那契數列的第十位 在控制臺中打印出來的是 55

技術分享圖片

那麽 第五十位呢?。。。。。。。。。

很好,我的瀏覽器卡死崩潰了

由此我們可知,這樣求斐波那契數列實在是太浪費性能了

既然有問題我們就來解決它

那麽 求斐波那契數列的時候是為什麽會浪費性能呢?

原因就是瀏覽器求了太多重復項

var i = 0; //聲明一個變量,用來記錄調用getFB()方法的次數
    function getFB(n){
      i++;
      if(n == 1 || n == 2){
        return 1;
      }else
{ return getFB(n-1) + getFB(n-2); } } console.log(getFB(20));// 我的瀏覽器求不出來這麽多項 所以換了小一點的數字
    console.log(i);

求斐波那契數列的第20位會調用13529次函數

技術分享圖片

那麽求第30位呢?

技術分享圖片

多達16萬次

第40位呢?第50 位呢?。。。。。。。

所以這個樣子實在是太浪費性能了

解決問題的思路:我們把已經求過的項用一個變量保存起來,如果下次還需要用到這個項就直接取出來用,而不是再去調用函數

 var i = 0;//
聲明一個變量i,記錄調用getFB這個函數的次數. //聲明一個對象obj,用來保存已經求過的項. var obj = {}; function getFB(n){ i++; //求n位是多少,就先去obj裏面看看,之前求過沒有,如果之前求過,就直接取出來使用. if(obj[n] != undefined){ //如果進到了這裏,說明當前這個n位已經求過,已經存進obj裏面了 return obj[n]; }else { //如果進到這裏來了,就說明當前這個n位之前沒求過,沒求過就求唄. if(n == 1 || n == 2){ obj[n] = 1; return 1; }else { obj[n] = getFB(n-1) + getFB(n-2); return obj[n]; } } } console.log(getFB(60)); console.log(i);

那麽我們就來看看結果吧

技術分享圖片

斐波那契數列的第60位大的嚇人,但是我們卻也只調用了117次函數,極大的提高了性能

使用遞歸解決斐波那契數列的性能問題