[英]Calculating Big O complexity of these algorithms?
我正在尝试找出以下两种算法的Big O表示法,但遇到了麻烦。
第一个是:
public static int fragment3 (int n){
int sum = 0;
for (int i = 1; i <= n*n; i *= 4)
for (int j = 0; j < i*i; j++)
sum++;
return sum;
} //end fragment 3
答案应该是O(n^4)
。 当我自己尝试执行此操作时,这就是我得到的:我查看第一个for循环,并认为它运行了n^2
logn次。 然后对于内部for循环,它将运行n次+外循环的运行时间,即n^3 logn
次。 我知道这是错误的,但是不明白。
对于下面的代码段,答案是O(n^9)
。
public static int fragment6(int n) {
int sum = 0;
for(int i=0; i < n*n*n; i++) {
if(i%100 == 0) {
for(int j=0; j < i*i; j += 10)
sum++;
} // if
else {
for(int k=0; k <= i; k++)
sum++;
} // else
} // outer loop
return sum;
} // fragment 6
当我尝试它时,我得到:外层for循环为n^3
。 对于if语句,我得到n
,对于第二个for循环,我得到n +
另一个for循环和if语句,使其成为n^5
。 最后,对于最后一个for循环,我得到n,并且所有结果加起来为O(n^6)
。
我在做什么错?获得O(n^9)
复杂度的正确方法是什么?
对于第一个。
让我们看一下内部循环。
在外循环的第一次迭代(i = 1)中,它运行1次。 在第二次迭代(i = 4)时,它将运行16(4 * 4)次。 在第三次迭代(i = 16)时,它将运行256(16 * 16)次。 通常,在外循环的第(k + 1)次迭代中,内循环运行 时代,作为
在那个迭代中。 所以迭代的总数将是
现在,我们这总数中将有多少个数字? 为了确定我们应该看看外部循环。 在其中,我成长为 ,直到达到
。 因此迭代总数为
。
这意味着内部循环的运行总数为
(通过从总和中除去所有数字,最后一个除外)。
现在我们知道,内部循环至少会运行 倍,所以我们不比O(n ^ 4)快。
现在,
求N
其中C是一个常数,所以我们不慢于O(n ^ 4)。
您计算big-O的方法完全是错误的,并且您已经犯了计算错误。
在某些常见情况下,您可以采用最坏情况的迭代次数并将它们相乘,但这不是一个可靠的方法,在以下情况下会失败:
for (i = 1; i < n; i *= 2) {
for (j = 0; j < i; j++) {
sum++;
}
}
在这里,外循环运行log_2(n)次,内循环最坏的情况是n次迭代。 因此,您使用的错误方法将告诉您此代码的复杂度为O(n log n)。
正确的方法是准确计算迭代次数,并仅在最后进行近似计算。 迭代次数实际上是:
1 + 2 + 4 + 8 + ... + 2^k
其中2 ^ k是小于n的2的最大幂。 该和为2 ^(k + 1)-1,小于2n。 因此,准确的复杂度为O(n)。
将这个想法应用于您的第一个示例:
for (int i = 1; i <= n*n; i *= 4)
for (int j = 0; j < i*i; j++)
sum++
i
取值4^0, 4^1, 4^2, ..., 4^k
,其中4^k
是小于或等于n^2
的4的最大幂。
对于给定的i
值,内部循环执行i^2
次。
因此,总的来说,内部sum++
会执行多次:
(4^0)^2 + (4^1)^2 + ... + (4^k)^2
= 2^0 + 4^2 + ... + 4^2k
= 16^0 + 16^1 + ... + 16^k
= (16^k - 1) / 15
现在根据k
的定义,我们有n^2/4 < 4^k <= n^2
。 所以n^4/16 < 4^2k <= n^4
,由于16^k = 4^2k
,我们得到内部循环执行的总次数是O( 16^k
)= O( n^4
)。
可以使用类似的方法来解决第二个示例。
第一种情况:
第二种情况:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.