Big o 为什么这个代码的运行时间是O(nlogn)?

Big o 为什么这个代码的运行时间是O(nlogn)?,big-o,Big O,这是课程算法的练习,关于Coursera的第1部分。他们说答案是O(N logn)。我不明白为什么: 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++; int和=0; 对于(int i=1;i让我们分析一下(将j重写为j) 执行。 但这是一个几何级数的

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

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++;
int和=0;
对于(int i=1;i让我们分析一下(将
j
重写为
j

执行。 但这是一个几何级数的和,所以这个和是

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))
让我们分析一下(将
j
重写为
j

执行。 但这是一个几何级数的和,所以这个和是

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))
最外循环的步数呈指数增长:

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)
然后您就得到了解决方案。

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

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)
然后您得到了解决方案。

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

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

你认为复杂度是多少?这很难回答,因为我不知道最里面的循环运行了多少次。但我原以为最外面的两个循环会分别运行对数n次。这是一个几何级数1、2、4、8、16…(其中第一个基项a=1,乘数r=2)请看这一页:如果我问了一些愚蠢的问题,我很抱歉,但是找到几何级数如何帮助我计算循环运行了多少次?你能举一个例子,将这个几何级数与上面的代码联系起来吗?你会期望什么样的复杂性?这很难回答,因为我不知道循环运行了多少次e最里面的循环运行。但我认为最外面的两个循环将分别运行对数n次。这是一个几何级数1,2,4,8,16…(其中基第一项a=1,乘数r=2)请看这一页:如果我问了一些愚蠢的问题,我很抱歉,但是找到几何级数如何帮助我计算循环运行了多少次?你能举一个例子,将这个几何级数与上面的代码连接起来吗?但是根据答案,那么j=1,j=2,j=3,j=4,j=5。当j运行时怎么会这样算术上?应该不是j=1,j=2;j=4,j=8…所以我不明白为什么j=log(N):12345…log(N)。你能详细解释一下吗?谢谢!谢谢Elyasin。我仍然在努力理解最后两行:j=log(N):1234568910…log(N)===========================================1+3+10+36+…+(N-1)+log(N)你有时间解释吗?@user2399525对不起,我再次更正了。j从
1到N
,但以指数级的步长。因此它循环
log(N)
次。检查并让我知道。我真的无法找到你的解决方案。我重新考虑了,我能想出的最好的方法是
O(N*log^2(N))
目前。O(N*log^2(N))这也是我提出的解决方案。但根据Coursera上的这门课程,这不是答案。但是谢谢!但是根据答案,那么j=1,j=2,j=3,j=4,j=5。当j以对数方式运行时,怎么会是这样呢?它不应该是j=1,j=2;j=4,j=8…所以我不明白为什么j=log(N):1 2 3 4 5…log(N)你能详细解释一下吗?谢谢!谢谢Elyasin。不过我还在试着理解最后两行:j=log(N):12345678910…log(N)=========================================1+3+10+36+…+(N-1)+log(N)你有时间解释一下吗?@user2399525对不起,我再次更正了。j从
1到N
,但是是指数级的。所以它循环lo