题目(2018-11-15)
斐波那契数列指的是类似于下面的数列:
1, 1, 2, 3, 5, 8, 13, ……
也就是,第n
个数是由前面两个数相加而来
完成fibonacci
函数,接受n
作为参数,可以获取数列中第n
个数,例如:
fibonacci(1) // => 1
fibonacci(2) // => 1
fibonacci(3) // => 2
...
实现
想到的最简单的实现就是利用递归:
const fibonacci = (n) => {
if (n === 2 || n === 1) {
return 1
}
return fibonacci(n - 1) + fibonacci(n - 2)
}
这样的问题时,当n比较大的时候(比如500),计算时间过长,程序会失去响应
所以需要进行改进,需要利用缓存,空间换区时间,在计算时多传入一个cache
对象,用于缓存计算过的数据:
const fibonacci = (n, cache = {}) => {
if (n <= 2) {
return cache[n] = 1;
}
if (cache[n]) {
return cache[n];
}
return cache[n] = fibonacci(n - 1, cache) + fibonacci(n - 2, cache)
};
console.time('1st');
console.log(fibonacci(1000));
console.timeEnd('1st');
// 4.346655768693743e+208
// 1st: 1.26904296875ms
console.time('2ed');
console.log(fibonacci(1000));
console.timeEnd('2ed')
// 41 4.346655768693743e+208
// 2ed: 0.637939453125ms
通过实验,这样是行得通的。
我们还可以进一步优化,由于缓存cache
在每次计算都是需要反问的,也就是说cache
是需要保留在内存中的,那么我们就可以构造一个闭包,让cache
保留在闭包中,供递归时使用:
const fibonacci = ((cache = {}) => n => {
if (cache[n]) {
return cache[n];
}
if (n <= 2) {
return cache[n] = 1;
}
return cache[n] = fibonacci(n - 1) + fibonacci(n - 2);
})();
console.time('1st');
console.log(fibonacci(1000));
console.timeEnd('1st');
// 4.346655768693743e+208
// 1st: 0.6630859375ms
console.time('2ed');
console.log(fibonacci(1000));
console.timeEnd('2ed')
// 41 4.346655768693743e+208
// 2ed: 0.186279296875ms
多次试验后发现,采用闭包的计算速度还是要快于直接传参的计算速度的,尤其是非首次计算,相对于首次计算时,由于cache
会保留在内存中,对计算速度的提高非常大