递归函数的运行时间T(n)

时间:2013-03-21 20:41:22

标签: c++ recursion time time-complexity fibonacci

我正在尝试计算此函数的T(n),我得出的是T(n)= T(n)+ T(n)+ O(1)。我有两个递归调用函数g()的拖曳T(n),然后是所有常数时间操作(如加法)的O(1)。我觉得我已经走了,所以任何帮助都会非常感激,我的数学背景也不太合理。

int g(int y) {
 if (y <= 0) {
  return 1;
 }
 else {
  return g(y - 1) + g(y - 2);
 }
}

2 个答案:

答案 0 :(得分:11)

计算time complexityFibonacci numbers取决于所使用的算法。至少有4种算法用于计算它们(具有不同的时间复杂度):

O(\phi ^ N)

首先我们提到我们可以通过查看递归斐波那契函数的call graph来解决这个问题。

调用图实际上是一棵树。

enter image description here

我们可以减少一切,找出这棵树有多少个节点。

F(n)的调用图中的节点数具有根和F(n-1)的调用图中的节点数+ F(n-2)的调用图中的节点数)。

我们将用L(n)表示F(n)中的节点数(你会发现字母L不是偶然的)。

如上所述,L(n)= L(n-1)+ L(n-2)+ 1.

但等等,还有更多!事实证明,这些完全 Leonardo numbers并且它们具有一般封闭形式:

enter image description here

"a(n) is the number of nodes in the Fibonacci tree of order n." A001595

O(n)的

另一种涉及memoization的算法具有复杂度O(n)(here is an exampleanother one)。这包括将T(n)的结果存储在一个向量中,并逐步计算n(1)的T(n)直到所需的n。

如果你真的想要真正正确,那么这也不是O(n),因为假设加法的数量成本为O(1),但是......随着F(n)变大,添加两个斐波那契数的成本是O(n)。你可以read more about this here,这是一个很好的阐述。因此,此实现的实际复杂性为O(n ^ 2)。

O(1)

还有另一种复杂度为O(1)的算法,假设您使用arbitrary precision arithmeticsome smart rounding。它来自Binet's formula。有关Binet公式的证明,请参阅使用生成函数的page 13 here上的第1.3节,或者,您可以找到eigendecomposition of the matrix,然后将其用于compute the nth power。 完成后,您的闭合公式将位于第n个幂矩阵的一个单元格中。

如果你想要非常精确,它实际上是O(log(n)),因为那是你用来计算Binet公式的exponentiation by squaring(也称为repeated squaring,二进制供电算法或二进制求幂)

通常我们假设x^n的取幂是O(1),但它不是,它是乘法数的O(log(n))。要非常精确,您必须考虑乘法的成本,这取决于所使用的multiplication algorithm

这是Binet的公式btw:

enter image description here

以下是Fibonacci sequence looks in matrix form

的方式

enter image description here

这是通过平方取幂:

enter image description here

更新2015-06-29

O(日志(n))的

还有另一种在O(log(n))中计算Fibonacci数的方法。 有两个身份使用

它们允许基于 F(n),F(n + 1)计算 F(2 * n + 1) F(2 * n)基于 F(n-1),F(n),F(n + 1)。 该算法找到 n most significant bit并向下迭代到最低有效位,同时使用沿途的标识来计算斐波纳契数。有一个algorithm here的实现。这两个身份可以在quadratic fieldℚ(√5)中导出(如前一个链接),也可以从上面提到的矩阵的第n和第2n次幂导出(参见第2.5节标题) 计算算法的page 23上的“矩阵方法” 斐波纳契数字很快被“L. L. Holloway”

答案 1 :(得分:0)

递归关系如下:

T(n)= T(n-1)+ T(n-2)+ O(1)

这不符合主定理下的任何情况,因为你的等式中没有T(n / b)形式的术语。

因此,我们必须采取一种略微奇怪的方法:

由于T(n-1),通过上面的定义,将等于T(n-3)+ T(n-2)+ O(1),你可以将T(n)写为:

T(n)= 2T(n-2)+ T(n-3)+ 2 * O(1)

由于T(n-2)= T(n-3)+ T(n-4)+ O(1),我们可以进一步简化T(n):

T(n)= 3T(n-3)+ 2T(n-4)+ 3 * O(1)

到现在为止,我们应该开始看到一种模式,但是我们只需要采取更好的措施。由于T(n-3)= T(n-4)+ T(n-5)+ O(1):

T(n)= 5T(n-4)+ 3T(n-5)+ 4 * O(1)

第一项的系数遵循斐波纳契数列的模式。在下一轮中,我们将以8T(n-5)为首要任期。第二个术语也跟随斐波那契序列,因为在下一轮我们将有5T(n-6)。第三个任期正如n那样增长。

所以,既然T(1)只是O(1),你最终会得到:

T(n)= x * O(1)+ y * O(1)+ n * O(1) 其中x是斐波纳契数列中的第n项,y是斐波纳契数列中的第(n-1)项。

从前面的术语来看,你可以看到我们的大O分析基本上只是基于n计算x的公式。

您可以在此处查看该公式:http://www.askamathematician.com/2011/04/q-is-there-a-formula-to-find-the-nth-term-in-the-fibonacci-sequence/

当你应用你的big-O分析时,这将归结为以下几点: O(1.6 ^ N)