确定特定功能的时间复杂度

时间:2018-04-17 21:57:49

标签: c time-complexity

这是我最近发现的来自算法和数据结构的旧考试之一的问题。我很难理解解决方案。 我需要查找函数的big-Obig-ϴbig-Ω边界:

void recursion(int n) {
 int i;
 if (n == 0) {
 return;
 }
 for (i = 0; i < n; i++) {
 recursion(i);
 }
}

所有三个解决方案都是2^n,我无法理解为什么。我已经尝试过写下来了,我甚至无法接近解决方案。如果有人能解释2^n来自何处,我将不胜感激。

4 个答案:

答案 0 :(得分:2)

由于这有点像家庭作业问题,这个答案在设计上是不完整的。

这类问题背后的通常技巧是创建一个递归方程。也就是说,recursion(k+1)的时间复杂度在某种程度上与recursion(k)的复杂性有关。只写下复发本身并不足以证明复杂性,你必须证明为什么复发是正确的。但是,对于2 n ,这表明recursion(k+1)的时间是recursion(k)的两倍。

  设p(k)表示recursion(k)的时间复杂度。由于recursion(0)立即返回,因此让T(0)= 1.对于k&gt; 0,给定recursion的{​​{0}}的迭代实施,因此为T(k) = Σ T(i) for 0 ≤ i < k
T(k+1) = Σ T(i) for 0 ≤ i < k+1
{{ 0}}你可以归纳证明T(k)= 2 k

答案 1 :(得分:2)

我们将总运行时间表示为f(n)。由于函数中的循环,f(n)实际上是f(i)的{​​{1}}之和,介于0和n-1之间。这是i项的总和。让我们尝试简化表达式。在这种情况下的标准技巧是找到一个互补的等式。让我们看看n的价值是什么。与前一种情况类似,它是f(n-1)f(i)在0和n-2之间的总和。所以现在我们有两个方程式:

i

让我们从第一个中减去第二个:

f(n)=f(1)+...+f(n-1)
f(n-1)=f(1)+...+f(n-2)

现在这是一个homogeneous linear recurrence relation with constant coefficients。 解决方案是即时的(有关详细信息,请参阅链接):

<强> F(N)= F(1)* 2 名词 = 2 名词

答案 2 :(得分:2)

让我们看一个更简单的递归,它已知为O(2 ^ n)

void fib(int n) {
    if (n < 3) {
        return 1;
    } else {
        return fib(n - 1) + fib(n - 2);
    }
}

在这里你可以看到,对于n&gt;的非平凡情况; 2,这将导致2 ^(n-2)次调用。例如,如果n = 5:

n = 5
    n = 4
        n = 3
            n = 2
            n = 1
        n = 2
    n = 3
        n = 2
        n = 1

有8(2 ^ 3)个递归调用,因为每个调用n&gt; 2产生两个递归调用,因此fib(n + 1)的递归调用是fib(n)的两倍。

所以对你的例子来说:

n = 3
    n = 2
        n = 1
            n = 0
        n = 0
    n = 1
        n = 0
    n = 0

所以当n = 3时,我们得到7次递归调用

对于n = 4

n = 4
    n = 3
        n = 2
            n = 1
                n = 0
            n = 0
        n = 1
            n = 0
        n = 0
    n = 2
        n = 1
            n = 0
        n = 0
    n = 1
        n = 0
    n = 0

在这里,我们有15个电话。查看上面的执行树,你可以看到recusrsion(4)基本上是递归(3)+递归(3)+ 1

n = 4
    n = 3          // + 1
        n = 2                //
            n = 1            //
                n = 0        // recursion(3)
            n = 0            //
        n = 1                //
            n = 0            //
        n = 0                //
    n = 2           //
        n = 1       //
            n = 0   // recursion(3)
        n = 0       //
    n = 1           //
        n = 0       //
    n = 0           //

所以一般来说,递归(n + 1)将有一个递归调用而不是2 *递归(n)....这基本上是每个+1到n加倍....这是O(2 ^ n)的

答案 3 :(得分:1)

r(n)   = r(n-1)+r(n-2)+...+r(0) // n calls.
r(n-1) = r(n-2)+r(n-3)+...+r(0) // n-1 calls.
r(n-2) = r(n-3)+r(n-4)+...+r(0) // n-2 calls.
.
.
.
r(1)   = r(0)                   // 1 call.
r(0)   = return;                // 0 call.

所以,

r(n)   = r(n-1)+r(n-2)+...+r(0)         // n calls.
       = 2 * (r(n-2)+...+r(0))          // 2 * (n - 1) calls.
       = 2 * ( 2 * (r(n-3)+...+r(0)) )  // 2 * 2 * (n - 2) calls.
.
.
.

这是=&gt;

2^(n-1) * (n - (n-1))

那就是

2^n calls...