首先介绍下斐波那契序列
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