首先介紹下斐波那契序列
0,1,1,2,3,5,8,...
就每一項的值都是前兩項相加得到的。
方法一: 最常見的遞歸實現
function fn(n) {
if(n === 0 || n === 1)
return n;
return fn(n-1) + fn(n-2);
}
console.log(fn(5))
代碼優美邏輯清晰,但是有重復計算的問題.
如:當n為5的時候要計算fibonacci(4) + fibonacci(3),當n為4的要計算fibonacci(3) + fibonacci(2) ,這時fibonacci(3)就是重復計算了。
運行 fibonacci(50)會出現瀏覽器假死現象,畢竟遞歸需要堆棧,數字過大內存不夠。
方法二: 使用閉包
改進遞歸-利用閉包特性把運算結果存儲在數組里,避免重復計算
var fn = function () {
let memo = [0, 1];
let fib = function (n) {
if (memo[n] == undefined) {
memo[n] = fib(n - 2) + fib(n - 1)
}
return memo[n]
}
return fib;
}()
fn(50)
方法三:循環遞推法
從下往上計算,首先根據f(0)和f(1)算出f(2),再根據f(1)和f(2)算出f(3),依次類推我們就可以算出第n項了,比遞歸的效率高很多
function fn(n) {
let current = 0;
let next = 1;
let temp;
for(let i = 0; i < n; i++) {
temp = current;
current = next;
next += temp;
}
return current;
}
借助解構賦值省略temp中間變量
function fn(n) {
let current = 0;
let next = 1;
for(let i = 0; i < n; i++) {
[current, next] = [next, current + next];
}
return current;
}
方法四: 尾調用優化
function fn(n, current = 0, next = 1) {
if(n == 0) return 0;
if(n == 1) return next;
return fn(n - 1, next, current + next);
}
函數的尾調用與尾遞歸,具體請看這里
https://www.cnblogs.com/ZheOneAndOnly/p/11368056.html