小技巧:前端用不同的方式实现斐波那契 fibonacci数列

 斐波那契 fibonacci 数列是经典的入门算法题,定义是:从第3项开始,前面相邻两项之和,构成了后一项。也就是,从第3项开始,每一项等于前面两项之和。

从定义看,最直观的就是递归,走一版:

版本1:

/**
 * 计算斐波那契数列第n项的值
 * @param {*} n 
 * @returns  第n项的值
 */
function fibonacci(n){
    if(n<=1) {
        return 1;
    }
    return fibonacci(n-1) + fibonacci(n-2);
}

const rest1 = fibonacci(10); // 89, 耗时约4毫秒
const rest2 = fibonacci(20); // 10946, 耗时约5毫秒
const rest3 = fibonacci(30); // 1346269, 耗时约13毫秒
const rest4 = fibonacci(40); // 165580141, 耗时约975毫秒
// 下面这个要慎重执行,会非常非常耗时
const rest5 = fibonacci(50); // 20365011074, 耗时约141740毫秒

从上述结果看到,随着参数(项数)的增加,到达一定的值后耗时将会相当长,因为需要递归调用的项是几何倍数增加的。

下面实现一版尾递归调用优化版本,理解上去会晦涩一点,但是性能会得到极大的提升,调用栈会极大的缩短。

版本2:

// 尾调用优化版本, ES6的实现都要求解释引擎底层实现尾调用优化。
// 在递归中使用尾调用优化,将会极大的提升递归的性能。
function fibonacci2(n, cur=1, total =1) {
    console.log(`fibonacci2 :: enter, n = ${n}, cur = ${cur}, total = ${total}`);
    if(n<=1) {
        return total;
    }
    return fibonacci2(n-1, total, total+cur);
}

const rest21 = fibonacci2(50); // 20365011074, 耗时也只有14毫秒,性能极大提升。
const rest22 = fibonacci2(10); // 573147844013817200000, 耗时也只有26毫秒

还可以通过Generator遍历器生成函数来实现,也很有意思。也是效率更高的一个版本

版本3:

function* fibonacci3(n){
    let [pre, cur] = [0, 1];
    for(let index = 0; index <n ;index++) {
        yield cur;
        [pre, cur] = [cur, pre + cur];
    }
}
function outputFib() {
    const start = new Date().getTime()
    const fibGen = fibonacci3(51); // 因为最后一项取不出来,因此这里参数加一个1
    let total=1;
    for(const rst of fibGen) {
        total = rst;
    };    
    console.log(`total = ${total}, duration = ${new Date().getTime() - start}`);
    // total = 20365011074, duration = 1
}
outputFib();
// 耗时基本只需要1毫秒或者0毫秒!!!
// 及时将参数调整成100,也是1毫秒或者0毫秒

版本2和版本3,从实际耗时看,版本3耗时更短。

从时间复杂度分析看的话,版本2的时间复杂度是T(n) =O(n) ,版本3的时间复杂度也是T(n) =O(n),但是实际的时候,版本3会多一倍的循环,但是耗时还更短!!!

有点不可思议。个人觉得是因为版本2中,涉及更多的数学运算,就比较耗时。

以上测试数据在我的电脑上进行,我的机器配置:

CPU: Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz   3.70 GHz

内存:16G

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值