提问者:小点点

这个代码的时间复杂度是多少? 是O(logn)还是O(loglogn)?


int n;
int p = 0;
for (int i = 0; i < n; i *= 2) {
    p++;
}
for (int j = 0; j < p; j *= 2) {
    //code;
}

这是来自Abdul Bari Youtube频道的代码(视频的链接),他们说这个的时间复杂度是O(log),但我认为是O(log),正确答案是什么?


共3个答案

匿名用户

修正初始值。 0乘以2将永远不会结束循环。

最后一个循环是o(log log N),因为p==log(N)。 但是,第一个循环是o(logn),因此它总共也是o(logn)

另一方面,一旦您将一些代码替换为//code,那么与第二个循环相比,第一个循环可以忽略不计,我们有:

O ( log N   +  X * log log N)
     ^ first loop
               ^ second loop

x刚好足够大时,可以将其视为o(log log N)。 然而严格地说,这是错误的,因为复杂性是关于渐近行为的,无论x有多大,对于n到无穷大,logn在某一点上总是大于x*loglogn

PS:我假设//code不依赖于N,即它具有恒定的复杂性。 如果不是这样,上述考虑就会改变。

PPS:一般来说,复杂度在设计算法时是很重要的。 在使用算法时,它是相当不相关的。 在这种情况下,对于n的特定值,您更关心实际运行时。 复杂性可能具有误导性,甚至导致对给定N的特定用例的错误期望。

匿名用户

的时间复杂度

int n;
int p = 0;
for (int i = 1; i < n; i *= 2) { // start at 1, not at 0
    p++;
}

是O(log(n)),因为你做了p++log2(n)次。 对数基数在大O表示法中并不重要,因为它只是按常数缩放。

for (int j = 1; j < p; j *= 2) {
    //code;
}

有O(log(log(n)),因为你只能通过乘法循环到p=log(n),所以你有O(log(p)),所以O(log(log(n))。

然而,两者加起来仍然是O(log(n)),因为O(log(n)+log(log(n)))=O(log(n)

匿名用户

你是正确的,完整代码的时间复杂度是O(log(n))。

但是,阿卜杜勒·巴里·西尔也是正确的,因为:-

在视频中,Abdul Sir试图找到循环的第二个的时间复杂度,而不是整个代码的时间复杂度。 再看一遍视频,好好听听他此时在说什么https://youtu.be/9sglbjxqwd4?t=568

再一次,他导出的是第二个循环的时间复杂度,而不是完整代码的时间复杂度。 请听他在视频中9分钟28秒时所说的话。

如果您的困惑是清楚的,请将此标记为正确。