斐波那契数列 算法

375 阅读2分钟

求解斐波那契数列第n项值

  • 大家都知道斐波那契数列,那么现在输入一个整数n,如何快速输出斐波那契数列的第n项呢?
  • 公式 : F(0) = 0, F(1) = 1, F(n) = F(n-1) + F(n-2), n >= 2;

公式都给你列好了,那就递归算法先走一个呗~

1. 递归算法

function Febonacci(n) {
    if(n < 2) {
        return n;
    } 
    return Febonacci(n-1) + Febonacci(n-2);
}

现在来分析一下复杂度:

假如我们现在要求解F(5),那么利用递归算法需要这么求解:

F(5)

F(5) = F(4) + F(3);

F(4) = F(3) + F(2); F(3) = F(2) + F(1);

F(3) = F(2) + F(1); F(2) = F(1) + F(0); F(2) = F(1) + F(0); F(1) = 1;

F(2) = F(1) + F(0); F(1) = 1; F(1) = 1; F(0) =0; F(1) = 1; F(0) = 0 F(1) = 1;

空间复杂度,即递归的深度,每次递归时需要的辅助空间,显而易见的为O(n);

时间复杂度,即递归的次数,可以看出的是该递归呈二叉树形式,递归次数即二叉树节点数2^h-1,h为树的深度,也就是n,所以时间复杂度为O(2^n),(⊙﹏⊙)可能并不会太快得到答案吧。

观察发现在中间计算各项值的时候,存在很多的重复计算,大大消耗了时间,于是我们来做一点优化,把计算过的值存起来,防止重复计算。

2. 时间优化

function Febonacci(n) {
    var arr = [];  //用于保存每项值
    arr[0] = 0, arr[1] = 1; //保存前两项
    for(var i = 2; i <= n; i ++) { //循环算出每一项的值,并保存到arr中
        arr[i] = arr[i - 1] + arr[i - 2];
    }
    return arr[n];
}

时间复杂度:O(n)

空间复杂度:O(n)

再仔细观察一下,我们发现每一项值的得出其实只依赖于它的前两项,那么是否可以对空间利用再进行优化呢?

3.空间优化

function Febonacci(n) {
    var n_2 = 0; //假设n为2,则n的前两项为0,1
    var n_1 = 1;
    var n_result = n >= 1 ? 1 : 0; //当n为0或1的时候,直接返回
    for(var i = 2; i <= n; i ++) { //n从2开始,依次往后累计
        n_result = n_1 + n_2;  //第n项的值等于n-1项 + n-2项
        n_2 = n_1;  //第n-2项的值 变为n-1项的值
        n_1 = n_result; //第n-1项的值 变为n项的值
    }
    return n_result;
}

这时,时间复杂度虽然还是O(n),但是空间复杂度已经降低为O(1)了哟。