为什么这段代码的运行时间为O(nlogn)?

时间:2015-07-17 13:17:14

标签: big-o

这是课程中的算法练习,练习第1部分。他们说答案是O(N log N)。我不明白为什么:

int sum = 0;
for (int i = 1; i <= N; i = i*2)
    for (int j = 1; j <= N; j = j*2)
        for (int k = 1; k <= j; k++)
            sum++;

有人可以告诉我内部循环运行的次数以及为什么答案是O(N log N)?

非常感谢您的帮助。

谢谢。

3 个答案:

答案 0 :(得分:3)

外部循环运行log(N)次。 两个内部循环组合运行Sum_ {x = 1} ^ {log(N)} 2 ^ x次,其中每个加数表示中间循环的一次迭代。 使用几何和公式,这使得总log(N)(1-2 ^(log(N)+1))/(1-2)= log(N)(2N-1)迭代,显然是O(N * logN)

答案 1 :(得分:1)

让我们分析(将j重写为J

for (int J = 1; J <= N; J = J*2)
    for (int k = 1; k <= j; k++)

假设N = 2^nJ的值为2^0, 2^1, 2^2, \ldots, 2^nk次循环执行J次,因此在J = 2^j时,它会执行2^j次。 总的来说,我们有

2^0 + 2^1 + 2^2 + \ldots + 2^n

执行。 但这是几何级数的总和所以总和是

2^0 (2^{n+1} - 1)(2 - 1) = 2^{n+1} - 1 = O(2^n) = O(N).

这个带有i的外圈会执行n = \log(N)次,我们总共有O(N\log(N))

答案 2 :(得分:1)

最外层循环的步骤呈指数级增长:

1 2 4 8 16 32 64 128 .... N

中间循环是相同的。

两者都有log(N)(基础2)步骤。

所以到目前为止你已经log(N) * log(N)了。

最里面的循环运行j次,其中j每次都由中间循环限制/给定。它运行log(N)次,迭代步长为1.这是一个系列:

j=1:      1
j=2:      1 2
j=4:      1 2 3 4
j=8:      1 2 3 4 5 6 7 8
j=16:     1 2 3 4 5 6 7 8 9 ... 16
...
j=N:      1 2 3 4 5 6 7 8 9 10 ... N
======================================
1 + 3 + 10 + 36 + ... + (1+2+3+4+5+...+N)

所以你有log(N) * log(N) * N作为上限(事实上,最里面的循环比N运行的步骤少。)

因此最后你有O(N*log^2(N))

我的分析不会产生O(N*log(N)),但并不意味着它不会。也许最内层循环的边界可以改进,因为我在这里简化了N作为所有循环的上限;我的意思是两个最里面的循环可能比O(N*log(N))更好。如果你能看到它们是O(N),那么你就得到了解决方案。