for(i=0; i<n; i++) // time complexity n+1
{
k=1; // time complexity n
while(k<=n) // time complexity n*(n+1)
{
for(j=0; j<k; j++) // time complexity ??
printf("the sum of %d and %d is: %d\n",j,k,j+k); time complexity ??
k++;
}
上述代码的时间复杂度是多少?我陷入第二个(for),我不知道如何找到时间复杂度,因为j小于k且不小于n。
我总是遇到与时间复杂性有关的问题,你们有一些好文章吗? 特别是关于步数和循环。
答案 0 :(得分:3)
从问题:
因为j小于k且不小于n。
这是完全错误的,我猜这是让你陷入困境的假设。我们知道k可以采取什么价值。在您的代码中,范围从1到n(包括)。因此,如果j小于k,则它也小于n。
来自评论:
我知道唯一的输入是n但是在第二个输入中取决于k而不是n。
如果一个变量取决于任何东西,它就在输入上。 j
取决于k
本身取决于n
,这意味着j
取决于n
。
但是,这还不足以推断出复杂性。最后,您需要知道的是printf
被调用的次数。
无论如何,外部for循环执行n次。我们可以将其考虑在内。
内部for循环的执行次数取决于k,它在while循环中被修改。我们知道k只需要从1到n的每个值。这意味着内部for循环首先执行一次,然后执行两次,然后执行三次,依此类推,直到n次。
因此,丢弃外部for循环,printf
称为1+2+3+...+n
次。这笔金额众所周知且易于计算:1+2+3+...+n = n*(n+1)/2 = (n^2 + n)/2
。
最后,printf
的来电总数为n * (n^2 + n)/2 = n^3/2 + n^2/2 = O(n^3)
。这是你的时间复杂性。
关于此类代码的最后说明。一旦你看到相同的模式几次,你很快就会开始认识到所涉及的复杂性。然后,当你看到那种带有因变量的嵌套循环时,你会立即知道每个循环的复杂性是线性的。
例如,在下文中,f
被称为n*(n+1)*(n+2)/6 = O(n^3)
次。
for (i = 1; i <= n; ++i) {
for (j = 1; j <= i; ++j) {
for (k = 1; k <= j; ++k) {
f();
}
}
}
答案 1 :(得分:1)
首先,简化代码以显示主循环。所以,我们有一个结构:
for(int i = 0; i < n; i++) {
for(int k = 1; k <= n; k++) {
for(int j = 0; j < k; j++) {
}
}
}
外循环运行n * n
次,但是你对这些信息的处理并不多,因为内循环的复杂性会根据你所在的外循环的迭代而改变,所以它不是就像计算外环运行的次数并乘以其他值一样简单。
相反,我会发现从内循环开始更容易,然后从最内部到最外部添加外部循环。
最内层循环的复杂性为k
。
使用中间循环,它是k
(上面的复杂度)k = 1 to n
的总和。所以1 + 2 + ... + n = (n^2 + n) / 2
。
使用外部循环,它完成了n
次,因此再次乘以n
。所以n * (n^2 + n) / 2
。
简化后,我们总共得到O(n^3)
答案 2 :(得分:-1)
上述代码的时间复杂度为:n x n x n = n ^ 3 + 1 + 1 = n ^ 3 + 2,对于3个循环加上两个常数。由于n ^ 3携带最大的生长速率,因此可以忽略常数值,因此时间复杂度将为n ^ 3。
注意:将每个循环作为(n)并获得总时间,每个循环中的多个(n)值。
希望这会有所帮助!