【问题标题】:Can one compute the nth Fibonacci number in time O(n) or O(1)? Why?可以在 O(n) 或 O(1) 时间内计算出第 n 个斐波那契数吗?为什么?
【发布时间】:2019-10-22 02:15:26
【问题描述】:

我问自己是否可以及时计算出第 n 个斐波那契数 O(n) 或 O(1),为什么?

谁能解释一下?

【问题讨论】:

  • 表示第n个斐波那契数的位数如何作为n的函数增长?

标签: algorithm time-complexity big-o fibonacci


【解决方案1】:

是的。它被称为Binet's Formula,或者有时,错误地,De Moivre 公式(真正的 De Moivre 公式是 another,但 De Moivre 确实在 Binet 之前发现了 Binet 公式) , 并涉及黄金比例 Phi。这背后的数学推理(见链接)有点复杂,但可行:

虽然它是一个近似公式,但斐波那契数是整数——因此,一旦您达到足够高的精度(取决于 n),您就可以将 Binet 公式中的数字近似为最接近的值整数。

然而,精度取决于常数,所以你基本上有两个版本,一个是浮点数,一个是双精度数,第二个也以恒定时间运行,但速度稍慢。对于 n,您将需要一个任意精度的数字库,并且它们的处理时间确实取决于所涉及的数字;正如@MattTimmermans 所观察到的,您最终可能会得到一个 O(log^2 n) 算法。这应该发生在足够大的 n 值上,无论如何你都会被大量库困住(但我需要对此进行测试以确定)。

否则,Binet 公式主要由两个取幂和一个除法组成(三个和和除以 2 可能可以忽略不计),而递归公式主要使用函数调用,而迭代公式使用循环。虽然第一个公式是 O(1),其他两个是 O(n),但实际时间更像 abn + cdn + e,a、b、c、d 和 e 的值取决于硬件、编译器、实现等。对于现代 CPU,a 很可能不会比 bd 大,这意味着 O(1) 公式应该几乎每个 n 都更快。但是迭代算法的大多数实现都以

开头
if (n < 2) {
        return n;
}

对于 n = 0 和 n = 1,这很可能更快。我相信 Binet 的公式对于任何超过个位数的 n 都更快。

【讨论】:

  • 这忽略了计算表达式的值需要多长时间的问题。
  • 因为所需的精度随着 n 的增加而增加,这至少需要 O(log^2 n) 时间。
  • 所以,由于黄金比例,有可能在 O(n) 中?
  • @Larry 不太...由于斐波那契数列的定义,O(n) 总是可能的(你总是可以从 F(n-1) 和 F(n) 得到 F(n) -2) 在 O(1)) 中。然后,这个特定的表达式可以被重写,并且无论 n 都可以立即求解,因此 O(1)。黄金比例是相同计算的不同结果。
  • @LSerni 所以下面的语句“可以在 O(n) 时间内计算出第 n 个斐波那契数。”是真的,因为斐波那契数列的定义。
【解决方案2】:

与其考虑递归方法,不如考虑自下而上构建序列,从 1+1 开始。

【讨论】:

  • 有什么区别 - 递归或迭代 - O(N) 在任何一种情况下都应该很明显,对吧?
  • @BitTickler no 在递归情况下,您正在多次求解一个斐波那契数。看看如果你想计算第四个数字,你应该计算第二个和第三个。但是要计算第三个,就必须计算第二个和第一个。所以第二个数字被计算了两次。
  • @BitTickler:由于递归案例执行f(n) = f(n-1) + f(n-2),这意味着每个调用都会额外递归两次,使其呈指数级。
  • 这不回答Can one compute the nth Fibonacci number in time O(n) or O(1)?
  • @WillemVanOnsem 取决于你如何进行递归。来自斐波那契的 Haskell wiki:haskell Prelude&gt; :{ Prelude| fib :: Int -&gt; Int Prelude| fib n = go n (0,1) Prelude| where Prelude| go n (a,b) | n == 0 = a Prelude| | otherwise = go (n-1) (b, a+b) Prelude| :} 请参阅:wiki.haskell.org/The_Fibonacci_sequence
【解决方案3】:

您也可以像这样使用矩阵m

1    1
1    0

并计算它的幂n。然后输出m^n[0,0]

【讨论】:

  • 这不回答Can one compute the nth Fibonacci number in time O(n) or O(1)?
  • @greybeard 实际上确实如此。求幂矩阵的第 (0,0) 个元素将是第 (n+1) 个斐波那契数。时间复杂度为 O(n),但您可以使用递归函数(m^n 是 m^n/2 * m^n/2 可选乘以 n 以处理 n 的奇数值),最终得到 O(记录 n)。
  • @LSerni 没有对位宽增长的说明(greybeard 在他在 OP 下方的第一条评论中提出的问题)我们无法解决复杂性,因为我们不知道基本操作是否是原子 O(1)。
猜你喜欢
  • 1970-01-01
  • 2020-03-22
  • 2011-08-27
  • 2022-12-10
  • 2017-01-08
  • 2018-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多