三个相互依赖的嵌套 for 循环的渐近分析
我要分析的代码片段如下:
int sum = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < i * i; j++)
for (int k = 0; k < j; k++)
sum++;
我知道第一个循环的时间复杂度为 O(n),但这就是我所得到的。我认为第二个循环可能是 O(n^2) 但我越想它就越没有意义。任何指导将不胜感激。
The code fragment I am to analyse is below:
int sum = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < i * i; j++)
for (int k = 0; k < j; k++)
sum++;
I know that the first loop is O(n) but that's about as far as I've gotten. I think that the second loop may be O(n^2) but the more I think about it the less sense it makes. Any guidance would be much appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
第一个循环执行
n
次。每次,值i
都会增长。对于每个这样的i
,第二个循环执行i*i
次。这意味着第二个循环执行1*1 + 2*2 + 3*3 + ... + n*n
次。这是平方和,其公式为 众所周知。因此,我们有第二个循环执行
(n(1 + n)(1 + 2 n))/6
次。因此,我们知道 j 总共有
(n(1 + n)(1 + 2 n))/6
个值,对于每个值,第三个循环将执行1 + 2 + ... + j = j(j+1)/2
次。实际上计算第三个循环总共执行了多少次是非常困难的。幸运的是,您真正需要的只是函数阶数的最小上限。您知道,对于
j
的每个(n(1 + n)(1 + 2 n))/6
值,第三个循环将执行 less超过n(n+1)/2
次。因此,您可以说操作sum++
将执行少于[(n(1 + n)(1 + 2 n))/6] * [n(n+1)/2 ]
次。经过快速心算,这相当于一个最大次数为 5 的多项式,因此您的程序是O(n^5)
。The first loop executes
n
times. Each time, the valuei
grows. For each suchi
, the second loop executesi*i
times. That means the second loop executes1*1 + 2*2 + 3*3 + ... + n*n
times.This is a summation of squares, and the formula for this is well-known. Hence we have the second loop executing
(n(1 + n)(1 + 2 n))/6
times.Thus, we know that in total there will be
(n(1 + n)(1 + 2 n))/6
values of j, and that for each of these the third loop will execute1 + 2 + ... + j = j(j+1)/2
times. Actually calculating how many times the third loop executes in total would be very difficult. Luckily, all you really need is a least upper bound for the order of the function.You know that for each of the
(n(1 + n)(1 + 2 n))/6
values ofj
, the third loop will execute less thann(n+1)/2
times. Therefore you can say that the operationsum++
will execute less than[(n(1 + n)(1 + 2 n))/6] * [n(n+1)/2]
times. After some quick mental math, that amounts to a polynomial of maximal degree 5, therefore your program isO(n^5)
.N 是整个程序的步骤数,M 是两个内部循环执行的步骤数,最后 K 是最后一个循环执行的步骤数。
容易看出K=j,需要j步来做。
(第一个参数是迭代器,第二个参数是上限,最后一个参数是我们要添加的参数)
这实际上是 n 个数字到 i*i 的总和。这意味着我们可以应用公式 ((n+1)*n)/2
这些都是众所周知的公式,玩一会儿后您会得到:
这应该是循环所采取的确切步数,但如果您有兴趣O 表示法,您可以注意到 n^5 是最强增长部分,因此解决方案是 O(n^5)
N is the number of steps of the entire program, M is the number of steps the two inner loops do and lastly K is the number of steps the last loop does.
It is easy to see that K = j, it takes j steps to do.
(First param is the iterator, second is the upper bound and last param is what we are adding)
This is actually now a sum of n numbers to i*i. Which means we can apply the formula ((n+1)*n)/2
These are both well known formulas and after a little playing you get:
This should be the exact number of steps the loop takes, but if you are interested in the O notation you can note that n^5 is the strongest growing part so the solution is O(n^5)
如果您有条不紊地使用西格玛表示法,您最终将得到以下结果:
If you proceed methodically using Sigma Notation, you'll end up with the following result:
尝试计算内部循环执行了多少次:
中间循环运行
所以它是
O(n^2)
。Try to count how many times the inner loop is executed:
The middle loop runs
So it is
O(n^2)
.