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"
答案 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] + 1
时mystery(..., N)
个分配的数量为:
N + N/2 + N/4 + ... + 1
假设N是2的幂,则该系列计算为2 * N - 1
。将会有相同数量的i
和log2(N)
测试增量“N&gt; 1”,递归调用神秘和分裂。
粗略地说,这是4 * N + 3 * log2(N)
次操作(假设它们相同
重量......虽然没关系)。
对于某些常数C1和C2,N
趋于无穷大的限制在C1 * N
到C2 * 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)