📜  javascript fibonacci 系列 - Javascript (1)

📅  最后修改于: 2023-12-03 14:42:24.697000             🧑  作者: Mango

JavaScript Fibonacci 系列

Fibonacci 系列是一个数学上很有趣的序列,它由 0 和 1 开始,之后的每一项都是前两项的和。即:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...

在 JavaScript 中,我们可以使用多种不同的方法来生成 Fibonacci 数列。

递归

递归是一种经典的生成 Fibonacci 数列的方法。通过定义一个递归函数来计算序列中的每一项:

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

这个函数首先检查参数 n 是否小于等于 1,如果是,就返回该参数本身。否则,它将调用自身来计算 n-1n-2 两个参数的结果,最后将这两个结果相加来得到 n 的结果。

时间复杂度

虽然递归是一种直观易懂的方法,但它的时间复杂度是指数级别的,因此对于较大的输入值,计算时间会非常长。

迭代

迭代是一种更高效的方法,因为它只需要计算每个项一次,而不像递归那样需要重复计算很多项。

function fibonacciIterative(n) {
  let a = 0;
  let b = 1;
  let c;
  if (n <= 1) {
    return n;
  }
  for (let i = 2; i <= n; i++) {
    c = a + b;
    a = b;
    b = c;
  }
  return b;
}

这个函数首先定义了三个变量,ab 分别初始化为 0 和 1,c 用于保存两者相加的结果。然后,如果 n 小于等于 1,直接返回 n;否则,使用 for 循环从 2 开始依次计算每个项的值。每次迭代中,将 ab 的值相加并将结果存储到 c 中,将 b 的值赋给 a,将 c 的值赋给 b。最后返回 b 即可。

时间复杂度

迭代方法的时间复杂度是线性的,与输入值的大小成正比。

动态规划

动态规划是另一种生成 Fibonacci 数列的经典方法。与迭代方法类似,它也只需要计算每个项一次。不同之处在于,动态规划将计算结果存储在数组中,以便后续使用。

function fibonacciDynamic(n) {
  let sequence = [0, 1];
  for (let i = 2; i <= n; i++) {
    sequence[i] = sequence[i - 1] + sequence[i - 2];
  }
  return sequence[n];
}

这个函数首先创建一个数组 sequence,包含序列中的前两个项:0 和 1。然后,使用 for 循环来计算从 2 开始的每个项,将计算结果存储到 sequence 数组中。最后返回 sequence[n] 即可。

时间复杂度

动态规划方法的时间复杂度与迭代方法相同,也是线性的。

尾递归

尾递归是一种优化过的递归方法,通过在递归函数的最后一步调用自身来减少计算开销。

function fibonacciTailRecursive(n, a = 0, b = 1) {
  if (n === 0) {
    return a;
  } else if (n === 1) {
    return b;
  } else {
    return fibonacciTailRecursive(n - 1, b, a + b);
  }
}

这个函数首先检查 n 的值。如果 n 等于 0,则返回 a;如果 n 等于 1,则返回 b;否则,将 n-1ba+b 三个参数传递给自身。这种方式可以更有效地利用 JavaScript 引擎的优化,避免栈溢出问题。

时间复杂度

尾递归方法与递归方法相同,时间复杂度为指数级别。

总结

以上是一些常见的生成 Fibonacci 数列的方法。每种方法都有其优缺点,具体使用时需要根据具体场景进行选择。在性能方面,迭代和动态规划方法通常是最快的,而递归和尾递归方法则需要更多的计算开销。