斐波那契数,通常用 F(n) 表示,形成的序列称为斐波那契数列。
    该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
         F(0) = 0,   F(1) = 1
         F(N) = F(N - 1) + F(N - 2), 其中 N > 1.
给定 N,计算 F(N)。

1. 递归

递归是最容易想到的一个方法,因为根据题意求每一个索引位置(索引大于2)上的值都等于前两个位置的值相加。

index:1 ——>  1
index:2 ——>  1
index:3 ——>  index:2 + index:1
index:4 ——>  index:3 + index:2
...
index:n ——>  index:n-1 + index:n-2

所以:

   var fibonacci =  function(index){
        if(index <= 0){
            return 0;
        }
        if(index <= 2){
            return 1;
        }
        return arguments.callee(index-1)+arguments.callee(index-2);
    }

上述代码中,使用arguments.callee来递归调用自身可以避免将递归调用的函数名写死掉,因为如果将这个函数赋值给了一个新的变量接受后,内部固定的递归调用就会报错。

2. 自顶向下进行数据的暂存

由于每一次递归都会从1开始求到index 这无疑大大浪费了性能,所以可以将数据暂存以下,这样下次再访问小于最大索引的索引值的时候,就是直接获取而不是再去递归。

 var arr2 = [0, 1, 1]
 var fibonacci2 = function(index) {
     if (index <= 0) {
         return 0;
     }
     if (arr2[index]) {
         return arr2[index];
     }
     arr2[index] = arguments.callee(index - 1) + arguments.callee(index - 2);
     return arr2[index];
 }

对于这个方法,如果第一次求的索引值(index)较大的话,会将这个索引之前的值都求完放进数组,那样之后在求比这个inde小的索引上的值的时候也是可以直接从arr2上面获取,所以会节省很多性能。这是我觉得比较适用的场景。

3. 自下而上进行数据的暂存

var fibonacci = function(index) {
    var arr = [0, 1, 1];
    for (var i = 3; i <= index; i++) {
        arr[i] = arr[i - 1] + arr[i - 2];
    }
    return arr[index];
}

相比于第一种递归的方法而言,这里进行一次循环之后会将arr数组中的index索引之前的位置都赋值好,拿最后一次来说,求arr[index]/arr[i]的时候(也就是i==index的时候),arr[i-1]和arr[i-2]上面已经有值了,所以是直接获取而不是再去递归。

4. 循环

因为当前索引上的值会等于前两个索引上的值相加,所以可以设置三个变量来保存,最后返回出来结果。

   var fibonacci = function(index) {
        if(index <= 0){
            return 0;
        }
       var prev = 1,
            next = 1,
            sum = 1;
        for (var i = 3; i <= index; i++) {
            sum = prev + next;
            prev = next;
            next = sum;
        }
       return sum;
    };

5. 循环优化

从上面的代码中可以发现,实际上只需要两个变量就可以实现了(prev表示前一个索引上的值,now表示现在索引上的值),所以此处对于代码进行一个优化:

var fibonacci = function(index) {
    if (index <= 0) {
     return 0;
    }
    var prev = 1,
        now = 1;
     for (var i = 3; i <= index; i++) {
        now = prev + now;
        prev = now - prev;
    }
     return now;
}

SANJIN
3 声望0 粉丝