这些谜团的运行时间是多少?

时间:2009-11-05 05:28:54

标签: algorithm big-o

mystery(int A[1..n], int n) { 
        // pre: n is a power of 2 for i=1..n {
        for i = 1...n {
            A[i] = A[i] + 1; 
        }
        if (n>1) mystery(A, n/2);
    }

}

我认为最糟糕的情况是,它在O(n)中运行,我是对的吗?


编辑:这是来自另一个旧考试(我们有答案),但以下算法在O(n * log n)时间运行(根据答案)。为什么这样?我虽然这两个应该只有一些常数不同。

void silly (int n)
    if (n>1)
        for (int i=0; i<n; i++)
            output "looping for fun"
        silly(n/2)
        for (int i=0; i<n; i++)
            output "looping for more fun"
        silly(n/2)
        for (int i=0; i<n; i++)
            output "looping for even more fun"

4 个答案:

答案 0 :(得分:3)

是的,这是O(n)。您可以通过检查值来理智地检查它:

A(1) = 1 iteration
A(2) = 2 + A(1) = 3
A(4) = 4 + A(2) = 7
A(8) = 8 + A(4) = 15
A(16) = 16 + A(8) = 31
A(32) = 32 + A(16) = 63
...

你看到它在线性缩放,其中A(n)基本上是n的线性因子。

回答评论:不,不是O(2n)或O(2n-1)。没有O(2n)。这都是O(n)。请参阅Plain english explanation of Big O

编辑:您的示例有一个关键区别:它自己调用两次而不是一次。理智再次检查结果。此外,这个版本有一个误导性的功能,因为循环重复三次,但三个在这里是恒定的,如前所述,没有O(n)所以我只计算一个循环:

A(1) = 1
A(2) = 2 + 2 * A(1) = 4
A(4) = 4 + 2 * A(2) = 12
A(8) = 8 + 2 * A(4) = 32
A(16) = 16 + 2 * A(8) = 80
A(32) = 32 + 2 * A(16) = 192
...

那么关系是什么?好吧,如果你解决A(n)(因为n是2的幂):

A(n) = n + 2 * A(n/2)
     = n + 2 * (n/2 + 2 * A(n/4))
     = 2n + 4 * A(n/4)
     = 2n + 4 * (n/4 + 2 * A(n/8))
     = 3n + 8 * A(n/8)

你可以解决一般情况:

A(n) = log2(n) * n + A(n/n)
     = log2(n) * n + 1 (since A(1) = 1)

这就是O(n log n)的来源。

答案 1 :(得分:1)

烨。调用A[i] = A[i] + 1mystery(..., N)个分配的数量为:

N + N/2 + N/4 + ... + 1

假设N是2的幂,则该系列计算为2 * N - 1。将会有相同数量的ilog2(N)测试增量“N&gt; 1”,递归调用神秘和分裂。

粗略地说,这是4 * N + 3 * log2(N)次操作(假设它们相同 重量......虽然没关系)。

对于某些常数C1和C2,N趋于无穷大的限制在C1 * NC2 * N操作范围内。换句话说,计算复杂度为O(N)

答案 2 :(得分:1)

我现在正在考虑这个问题的期中考试!

如何,让我们调用此算法的运行时间T(n)。 for循环需要n次,函数调用自身的值为n / 2。所以T(n)= T(n / 2)+ n。

我们可以使用Master Theorem来解决这种复发问题,我们发现该算法采用了Theta(n)

答案 3 :(得分:0)

这是O(n)

推导。您可以使用Master Theorem或更简单的扩展方式派生它:

假设mystry()的运行时为T(n),则为:

T(n) = n + T(n/2)   # n for the loop, T(n/2) for the recursive call
     = n + (1/2)n + T(n/4)
     = n + (1/2)n + (1/4)n + (1/8)n + ...
     = n (1 + 1/2 + 1/4 + 1/8 + ...)
     = n \Sum^{\inf}_{i=0} (1/2^i)
     = n * (2)
     = 2 n = O(n)