我正在做一个测验-除以下片段外,我一切都很好。帮助我了解这是哪种表示法?
我的选择是:O(n ^ 2),O(n ^ 3),O(nlogn)和O(n + n ^ 2)
代码段为:
for (int i = 0; i < n; i++) {
System.out.println("hello");
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) { // NOTE j < i here.
System.out.println("hello");
}
}
答案 0 :(得分:2)
第一个循环很简单:主体精确运行n
次,所以运行O(n)
。
第二个需要更多的思考。显然,外循环运行了n
次,但是内循环主体多久执行一次?第一次通过外循环,我们有i == 0
,所以内循环主体被执行0次(j < i
也为j == 0
是错误的)。第二次i == 1
,因此执行内循环主体1次。通常,它i
执行了i = 0, ..., n-1
次。
因此,内循环主体的执行总数为S
,为S = 0 + 1 + ... + n-1
。现在有一个很好的技巧,可以将其变成闭合形式的方程式。写下一次,然后再反向写下一次:
S = 0 + 1 + ... + n-2 + n-1
S = n-1 + n-2 + ... + 1 + 0
然后将两个方程式相加:
S = 0 + 1 + ... + n-2 + n-1
S = n-1 + n-2 + ... + 1 + 0
------------------------------- +
2*S = n-1 + n-1 + ... + n-1 + n-1
因此2*S
等于n
乘以n-1
。由此,我们很容易找到S = n * (n-1) / 2
。可以将其重写为S = ½*n^2 - ½*n
。在big-O形式中,只有最高阶的项保留下来,常数½
无关紧要,因此O(n^2)
就是这样。
获得相同结果的另一种“手摇式”方法是:内部循环平均运行n/2
次(给定或取一个),而外部循环再次运行n
次给O(½*n*n) = O(n^2)
。
结合第一个循环的O(n)
(与O(n^2)
渐近无关),预期答案可能是O(n^2)
。
但是请注意,O(n+n^2)
在技术上也是正确的,因为O(n + n^2) = O(n^2)
。同样,低阶项n
渐近无关紧要。从技术上来说,即使O(n^3)
也是正确的,因为n^3
主导n^2
;但是,复杂度既不是Ω(n^3)
也不是θ(n^3)
。
答案 1 :(得分:1)
(这就是我的想法,我没有评论,因为我没有足够的声誉,但是我想把它排除在外)
第一个循环是线性的,因此复杂度仅为O(N)
。
但是,对于第二个/第三个循环,第二个循环是循环N
次的循环。内部循环将运行N/2
时间,因为j
总是小于i
(并且永远不等于)。因此,这些循环的复杂度为N(N/2)
或N^2/2
。由于Big O是一个常数,N/2
和N - 1
是同一时间,所以我们也可以说它是N(N-1)
或N^2 - N
。
如果将两个复杂度加在一起,我们将得到(N) + (N^2 - N)
,得到N^2
。因此,最终结果为O(N^2)
。