斐波那契数列(Fibonacci sequence)

990 阅读2分钟

1.定义

斐波那契数列(Fibonacci sequence),又称黄金分割数列、因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”,指的是这样一个数列:1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(1)=1,F(2)=1, F(n)=F(n-1)+F(n-2)

2. 递归实现以及性能思考

递归实现

var count = 0;var fibonacci = (n) => { 
    count++;   
    return n === 1 || n === 2 ? 1 : (fibonacci(n - 1) + fibonacci(n - 2))
};
fibonacci(10);console.log(count);//被调用109次

这是斐波那契数列最基本的递归实现。但是该递归实现方法复杂度过高。

对性能的思考

假如说n=5,那么可以用下图来表示计算的次数:


可以计算出方法被调用次数:

2^0 + 2^1 + 2^2 + ... + 2^(n-2) + 2^(n-3)+...+2^1

2^10 = 1024

2^20 = 1,048,576

当数量稍微大一点的时候计算机的cpu就不行了。那我们怎么优化这个方法呢?

3.优化方案

空间换时间思想

基于普通递归方法,我们可以把每次计算结果储存起来,如果计算过了就直接取值,没有计算才会调用计算

var count = 0;
var obj = {};
var fibonacci = (n) => {
    count++;
    if (n === 1 || n === 2) {
        obj[n] = 1;
        return 1;
    }

    if (obj[n]) {
        return obj[n]
    }
    const res = (fibonacci(n - 1) + fibonacci(n - 2));
    obj[n] = res;
    return res;
};
fibonacci(10);
console.log(count);//该方法被调用17次

es6解构实现

var fibonacci = (n) => {    
    let [a, b] = [0, 1];    
    for (let i = 0; i < n; i++) {        
        [a, b] = [b, a + b]    
    }    
    return a;
};
fibonacci(10);

Array数组实现

Array(n).fill快速填充一个数组长度为n的数组

var fibonacci = () => {    
    const res = Array(n).fill().reduce(([a, b]) => { return [b, a + b] }, [0, 1]);    
return res[0];
};
fibonacci(10);

generator实现

function* getFibonacci() {    let [a, b] = [0, 1];    while (true) {        [a, b] = [b, a + b];        yield a;    }}var fibonacci = (n) => {    let res = {        value: 0    };    const fibo = getFibonacci();    for (let i = 0; i < n; i++) {        res = fibo.next();    }    return res.value;};fibonacci(10);

ES6解构,Array,Generator这三种原理都是一样的,只不过套了不同的壳子而已。