返回

解构斐波那契,七种JavaScript实现剖析大法<

前端

斐波那契数列的定义

斐波那契数列(Fibonacci sequence),又称黄金分割数列,是指这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下递推关系定义:

F(0) = 0, F(1) = 1

F(n) = F(n-1) + F(n-2)(n ≥ 2)

换句话说,斐波那契数列的每一个数字都是由前两个数字之和构成的。

用JavaScript实现斐波那契数列

  1. 递归法:从后往前解题

这种方法的实现非常直观,也很符合我们对斐波那契数列的认知,因为我们知道斐波那契数列的第N项由它的前两项相加得出,所以我们只需要递归地计算出前两项的值,就能得到第N项的值。

function fibonacci_recursive(n) {
  if (n === 0) {
    return 0;
  } else if (n === 1) {
    return 1;
  } else {
    return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2);
  }
}
  1. 循环法:从前往后解题

循环法从第0项开始依次计算出每项的值,不需要递归调用,循环的次数就是斐波那契数列的项数。

function fibonacci_loop(n) {
  if (n === 0) {
    return 0;
  } else if (n === 1) {
    return 1;
  } else {
    var first = 0;
    var second = 1;
    for (var i = 2; i <= n; i++) {
      var temp = first + second;
      first = second;
      second = temp;
    }
    return second;
  }
}
  1. 递推法:节约空间的循环法

递推法实际上是循环法的优化版本,它利用了斐波那契数列的特点:第N项只与它的前两项有关。所以,我们可以只保存前两项的值,用一个变量来记录当前项的值,循环的次数就是斐波那契数列的项数减去2。

function fibonacci_iterative(n) {
  if (n === 0) {
    return 0;
  } else if (n === 1) {
    return 1;
  } else {
    var first = 0;
    var second = 1;
    for (var i = 2; i <= n; i++) {
      var temp = first;
      first = second;
      second = temp + second;
    }
    return second;
  }
}
  1. 动态规划法:利用数组保存中间结果

动态规划法是一种从下到上的解题方法,它利用了斐波那契数列的递推关系,将计算出的中间结果保存在一个数组中,避免了重复计算。

function fibonacci_dp(n) {
  var fib = new Array(n + 1);
  fib[0] = 0;
  fib[1] = 1;
  for (var i = 2; i <= n; i++) {
    fib[i] = fib[i - 1] + fib[i - 2];
  }
  return fib[n];
}
  1. 生成器法:无需一次性计算出所有结果

生成器法利用了生成器的特性,可以按需计算斐波那契数列的每一项。

function* fibonacci_generator() {
  var first = 0;
  var second = 1;
  while (true) {
    yield first;
    var temp = first;
    first = second;
    second = temp + second;
  }
}
  1. 闭包法:利用闭包保存状态

闭包法利用了闭包的特性,可以保存函数内部的变量,从而可以实现斐波那契数列的计算。

function fibonacci_closure() {
  var first = 0;
  var second = 1;
  return function(n) {
    if (n === 0) {
      return first;
    } else if (n === 1) {
      return second;
    } else {
      var temp = first;
      first = second;
      second = temp + second;
      return second;
    }
  };
}
  1. 尾递归法:优化递归调用

尾递归法是一种特殊的递归方式,它将递归调用放在函数的最后一行,这样可以优化递归调用的效率。

function fibonacci_tail_recursive(n, first, second) {
  if (n === 0) {
    return first;
  } else if (n === 1) {
    return second;
  } else {
    return fibonacci_tail_recursive(n - 1, second, first + second);
  }
}