Skip to content

💤

定义

F(n) = F(n-1) + F(n-2); 其中F(1) = 1F(2) = 1

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

循环实现

javascript
// 1.
function fibonacci(n) {
  if (n <= 2) return 1

  let a = 1,
    b = 1
  for (let i = 3; i <= n; i++) {
    ;[a, b] = [b, a + b]
  }
  return b
}

// 2.
function fibonacci(n) {
  if (n <= 2) return 1

  let dp = [0, 1, 1] // 初始化前两个值
  for (let i = 3; i <= n; i++) {
    dp[i] = dp[i - 1] + dp[i - 2]
  }

  return dp[n]
}

普通递归

javascript
function fibonacci(n) {
  if (n <= 2) return 1

  return fibonacci(n - 1) + fibonacci(n - 2)
}

尾递归

TCO - Tail Call Optimization 尾调用优化

尾调用就是一个出现在另一个函数“结尾”出的函数调用。这个调用结束后就没有其余事情要做了(除了可能要返回结果值)。

支持 TCO 的引擎能够意识到fib(n - 1, b, a + b)调用位于尾部,这意味着上一个fib(..)基本上已经完成了,所以调用一个新的fib(..)不需要创建一个新的调用栈,而是可以重用当前调用栈。这样不仅速度更快,也更节省内存。

javascript
// 1. 测试得: 该方法远比下边尾递归实现更快,数据越大,差距越大。原因不明
function fibonacci(n) {
  function fib(n, a, b) {
    if (n === 1) return a
    return fib(n - 1, b, a + b)
  }

  return fib(n, 1, 1)
}

// 2. 慢于 1 ,但快于普通递归实现
function fibonacci(n, a = 1, b = 1) {
  if (n === 1) return a
  return fibonacci(n - 1, b, a + b)
}