对于下面mystery(n)
函数的伪代码,找到其渐近最坏情况运行时间f(n)
的紧上限和下限。也就是说,找到g(n)
使得f(n)
∈Θ(g(n))
。 (假设n是正整数)
Mystery (n ){
c ←1 | (constant)
for i ←1 to n | n
do for j ←i to n | j
do for k ← n down to n/2 | n/2
do c ← c + 1 | (constant)
print c | (constant)
}
总时间:(n / 2)nj(不确定)
侧面的时间标签是我到目前为止所知道的。对于这个问题,似乎最佳和最差情况运行时间之间没有区别?另外,如何找到此方法的上下限?任何建议都会很棒。或者我可以阅读的资源,因为我的教科书对这个主题非常模糊。
答案 0 :(得分:3)
j
不应出现在您的公式中,因为j
也是n
的函数。
每当你有一个依赖于外部循环变量的循环时,我发现最容易查看求和公式以找出复杂性。
所以外循环肯定会运行n
次,而最里面的循环肯定会运行n/2
次,但总的来说是n/2 ∈ O(n)
。
所以,让我们看看中间循环。
中间循环在第一次迭代时运行(n-1)
次,在第二次迭代时运行(n-2)
次,一直到(n-n)
,等于0次。您可以将这些术语重新排列为0到n的总和。我们知道这个总和等于n(n+1)/2
。
由于此公式表示外部循环和中间循环的组合,因此您可以简单地将最里面的循环相乘以得到n(n+1)n/(2*2) == n^2(n+1)/4
的最终公式。
你应该意识到的一个概念性事情是,因为c
只是一个计数器,并且它在每次迭代时递增,c
可以被认为是此运行时复杂性的直接表示算法
您可以通过计算c
来验证此结果。这是一个用C语言编写的示例程序,用于演示此算法:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int c = 0;
int n = 10;
if (argc > 1) {
n = atoi(argv[1]);
}
for (int i = 1; i <= n; ++i) {
for (int j = i; j <= n; ++j) {
/* Note that I've changed k to run from 0 to n/2 instead of n
down to n/2, but this doesn't change the result. */
for (int k = 0; k < n/2; ++k) {
++c;
}
}
}
printf("c == %d; n^2(n+1)/4 == %d\n", c, n*n*(n+1)/4);
}
这里是输入2,4,8,32和64的上述程序的输出:
c == 3; n^2(n+1)/4 == 3
c == 20; n^2(n+1)/4 == 20
c == 144; n^2(n+1)/4 == 144
c == 8448; n^2(n+1)/4 == 8448
c == 66560; n^2(n+1)/4 == 66560
答案 1 :(得分:1)
Mystery (n ){
c ←1 | (constant)
for i ←1 to n | n
do for j ←i to n | j
do for k ← n down to n/2 | n/2
do c ← c + 1 | (constant)
print c | (constant)
}
关于运行n
次的外循环,你是对的。然而,对于i = 1,下一个循环将运行n次,对于i = 2,n = 1次,...,对于i = n-1,运行2次,对于i = n,运行一次。平均而言,j
循环将运行n/2
次,因此该中间循环也被认为是O(n)循环。当您组合所有三个嵌套循环时,这会使总运行时复杂度为O(n ^ 3)。