使用遞歸解決斐波那契數列的性能問題
阿新 • • 發佈:2018-08-08
還需 都是 來看 次數 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次函數,極大的提高了性能
使用遞歸解決斐波那契數列的性能問題