我正在努力寻找此代码的时间复杂性。
for (int i = 0; i <= n - 1; i++)
for (int j = i + 1; j <= n - 1; j++)
for (int k = j + 1; k <= n - 1; k++)
我的尝试: 我们可以用以下形式编写这个循环:
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
for (int k = 1; k <= n; k++)
现在这个循环的大哦是O(n ^ 5)。我纠正还是做错了?
答案 0 :(得分:4)
添加了计数器的代码的第一个变体:
int count = 0
for (int i = 0; i <= n - 1; i++)
for (int j = i + 1; j <= n - 1; j++)
for (int k = j + 1; k <= n - 1; k++)
count++;
这计算(i,j,k)的每个组合,其中 0&lt; = i&lt; j&lt; k&lt; Ñ。这对应于您可以从 n 元素中选择3个元素的方式,而不考虑它们的顺序。该号码有a formula:
n(n-1)(n-2)/ 3! = n 3 / 6 - n 2 / 2 - n / 2
第二种变体:
int count = 0
for (int i = 0; i <= n - 1; i++)
for (int j = 0; j <= n - 1; j++)
for (int k = 0; k <= n - 1; k++)
count++;
...计算您可以从 n 项目中选择3的方式,但订单很重要,并且允许在3个选项中重复。这个数字很容易导出,因为 i,j,k 是独立的,每个都可以得到 n 不同的值,所以总数是:
n 3
现在它们代表了同样的时间复杂性:
O(n 3 / 6 - n 2 / 2 - n / 2)= O(n 3 )< / em>的
这是因为properties of big O:
如果函数可能被 n 中的多项式所限制,那么当 n 趋于无穷大时,可以忽略多项式的低阶项。
和
乘以常数
设 k 为常数。然后:
O(kg)= O(g)如果 k 非零。
答案 1 :(得分:1)
现在这个循环的大哦是O(n ^ 5)。我纠正还是做错了?
不,这不正确。复杂性为O(n^3)
。
简单来说,你可以这样想:
从0
开始,到达n-1
步骤为1的每个for循环中执行的最大步骤为n
。因此,如果您有两个循环,一个嵌套在另一个循环中,那么对于您在外部循环中创建的每个步骤,您将在嵌套循环中执行n
个步骤。鉴于您将在外循环中执行的步骤为n
,很明显,最后您将执行n^2
步骤。
基于以上所述,您可以在以下情况下轻松绘制:
for(int i=0; i<=n-1; i++)
{
for(int j=0; j<=n-1; j++)
{
for(int k=0; k<=n-1; k++)
{
}
}
}
您将执行n^3
步骤。因此复杂性大约为O(n^3)
。
答案 2 :(得分:1)
这些循环是否嵌套?如果是这样,那么你就可以重新编写循环,以便更容易理解。虽然我会给每个循环一个不同的迭代器名称,以避免混淆:
for (int a = 1; a <= n; a++) {
for (int b = 1; b <= n; b++) {
for (int c = 1; c <= n; c++) {
...
}
}
}
实际上,您可以将这些变量重命名为任何您想要更容易推理的变量。怎么样:
for (int street = 1; street <= n; street++) {
for (int house = 1; house <= n; house++) {
for (int room = 1; room <= n; room++) {
...
}
}
}
现在,问题变成了,如果我必须访问n个城市的n个房间的n个房间,我需要访问多少个房间?
希望你能看到答案是n * n * n,即n ^ 3。
获得答案的快捷方式是看到你有3个嵌套for循环从1到n,所以答案是n ^ 3.
答案 3 :(得分:0)
如果您有疑问,并且想要说服自己只是进行一些测试:
#include <stdio.h>
int main()
{
int count1=0,count2=0;
int n=100;
for (int i = 0; i <= n - 1; i++)
for (int j = i + 1; j <= n - 1; j++)
for (int k = j + 1; k <= n - 1; k++)
count1++;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
for (int k = 1; k <= n; k++)
count2++;
printf("count1 %d count2 %d n %d\n",count1,count2,n);
return 0;
}
结果:
count1 161700 count2 1000000 n 100
显然,第二个循环运行100**3
次=&gt;为O(n ** 3)
第一个循环由于边界而运行较少,但它仍然是线性的(在边界上没有除法运算)=&gt; O(n ** 3)即使它更快也是如此。