JS中的斐波那契数列解读

466 阅读2分钟

定义:

斐波那契数列-维基百科

公式:

斐波那契数列公式

如果 F0 = 0F_0\ =\ 0 为第一项,F1 = 1F_1\ =\ 1 为第二项,那么从第三项开始,以及之后的每一项都等于前两项的和。

JavaScript 中如何求斐波那契数列中的数呢?

JavaScript中的实现:

《JavaScript 高级程序设计(第四版)》在第 10 章,关于函数尾调用优化代码(P309)列举了一个通过递归函数计算斐波那契数列的例子:

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

console.log(fib(0)); // 0
console.log(fib(1)); // 1
console.log(fib(2)); // 1
console.log(fib(3)); // 2
console.log(fib(4)); // 3
console.log(fib(5)); // 5
console.log(fib(6)); // 8

这个函数会给浏览器带来麻烦,比如说当调用 fib(1000) 的时候。

以下是重构为满足尾调用优化条件的形式,使用两个嵌套的函数,外部函数作为基础框架,内部函数执行递归:

// 基础框架
function fib(n) {
    return fibImpl(0, 1, n);
}

// 执行递归
function fibImpl(a, b, n) {
    if (n === 0) {
        return a;
    }
    return fibImpl(b, a + b, n - 1);
}

迭代循环的实现:

function fib(n) {
    let currNum = 0,
        prevNum = 1,
        arr = [],
        count = 0;

    while(count <= n) {
        arr.push(currNum);
        currNum += prevNum;
        prevNum = currNum - prevNum;
        count++;
    }
    return arr[n];
}

console.log(fib(0)); // 0
console.log(fib(1)); // 1
console.log(fib(2)); // 1
console.log(fib(3)); // 2
console.log(fib(4)); // 3
console.log(fib(5)); // 5
console.log(fib(6)); // 8

console.log(fib(10)); // 55

解析: 斐波那契数列图解

currNum 是计算斐波那契数列中 FnF_n 的值。 prevNumFn+1F_{n+1}FnF_n 的差值,该差值除第一项以外,可以看出它也是一个斐波那契数列。

它的规律就是: 下一次循环时 currNum 的值是:当前值 + 差值。如上图中左边部分黑色箭头指向所示。

所以,每次循环完应该更新 currNum 的值,用 JavaScript 代码表示就是:

currNum = currNum + prevNUm;

可以简写为:

currNum += prevNum;

下一次循环时 prevNum 的值是:更新后的 currNum 的值 - 当前 prevNum 的值。

prevNum = currNum - prevNum;