该递归块的时间复杂度

时间:2018-08-11 20:48:00

标签: recursion time-complexity

int recursiveFunc(int n) {
    if (n == 1) return 0;
    for (int i = 2; i < n; i++)
        if (n % i == 0) return i + recursiveFunc(n / i);
    return n;
}

我知道复杂度=从根节点到叶节点的树的长度*叶节点的数量,但很难求解。

1 个答案:

答案 0 :(得分:2)

这是一个棘手的问题,因为运行时高度依赖于您提供的输入数字,而大多数递归函数都不会这样做。

对于初学者,请注意,此递归的工作方式是先输入数字,然后输入数字

    如果号码是素数,
  1. 返回而不会再进行任何呼叫,或者
  2. 递归地调用数字除以该适当因子的数字。

这意味着,在一种情况下,调用数字n的函数将执行Θ(n)且不进行调用(如果数字为素数,则发生此情况),而在另一种情况下,将执行Θ(d ),然后对数字n / d进行递归调用,如果n是合成的并且是n的最大除数,则会发生这种情况。

我们将用来分析该函数的一个有用事实是,给定一个复合数n,n的最小因数d永远不会大于√n。如果是,那么对于其他一些因子f,我们将拥有n = df,并且由于d是最小的适当除数,因此我们将拥有f≥d,因此df>√n√n = n,这是不可能的

考虑到这一点,我们可以认为此函数的最坏情况运行时为O(n),实际上,这是在n为素数时发生的。这是怎么看的。想象一下,如果该函数最终进行了递归调用,则可能花费最坏的时间。在这种情况下,该函数最多可以完成Θ(√n)个工作(假设我们的最小除数尽可能大),然后递归调用最大为n / 2的数字(这是绝对值)。作为递归调用的一部分,我们可以获得最大的数目。在这种情况下,我们将在尽可能多地工作的悲观假设下获得这种递归关系

  

T(n)= T(n / 2)+√n

这通过主定理解决了Θ(√n),这比我们要以质数作为输入要完成的工作要少。

但是,如果相反,我们在一定数量的迭代中进行了尽可能多的工作,然后以质数结束并停止,该怎么办?在这种情况下,使用迭代方法,我们将看到完成的工作

  

n 1/2 + n 1/4 + ... + n / 2 k

如果我们在k次迭代后停止,就会发生这种情况。在这种情况下,请注意,当我们选择k尽可能小时,此表达式将最大化-这相当于尽快停止,如果我们为n选择素数,则会发生这种情况。

因此,从这个意义上讲,此函数最坏的运行时间是Θ(n),这在n是质数的情况下发生,并且复合数的终止速度比此快得多。

那么这个功能有多快?好吧,例如,假设我们有一个形式为p k 的数字,其中p是一些质数。在这种情况下,此函数将完成Θ(p)的工作,以发现p为素数,然后递归调用数字p k-1 。如果考虑一下它将是什么样子,则此函数最终将完成Θ(p)工作Θ(k)次,而总运行时间为Θ(pk)。并且由于n = p k ,我们将有k = log p n,因此运行时间为Θ(p log p n) 。在p = 2或p = 3时最小化了这种情况,在任何情况下都使我们的运行时间为Θ(log n)。

我不确定这是最好的情况,尽管我不确定。但这意味着……

  • 最坏情况的运行时间肯定是Θ(n),出现在质数上,并且
  • 最佳情况下的运行时是O(log n),我相当确定这是一个严格的界限,但我不确定100%如何证明。