我有以下算法,运行时复杂度为O(N ^ 2),但我希望对它有更深入的了解,而不仅仅是记住常见的运行时。
在内部for循环考虑中使用i+1
分解并分析它的正确方法是什么?
void printunorderedPairs(int[] array) {
for(int i=0; i<array.length; i++) {
for(int j=i+1; j<array.length; j++) {
System.out.println(array[i] + "," + array[j]);
}
}
}
修改
询问如何分析特定问题
答案 0 :(得分:1)
分解并分析它的正确方法
拿铅笔和纸,放下一些未打开的环:
i inner loops per i
-------------------------------
1 length - 1
2 length - 2
.. ..
k length - k
.. ..
length - 1 1
length 0
现在,为了获得所需的总时间,让我们总结内部循环:
(length - 1) + (length - 2) + ... + (length - k) ... + 1 + 0
这是一个算术级数,其总和是
((length - 1) + 0) / 2 * length == length**2 / 2 - length / 2 = O(length**2)
答案 1 :(得分:0)
设T
=内循环运行的次数。
大约一半时间,i<array.length/2
时,它至少运行array.length/2
次。因此,对于大约array.length / 2外部迭代,内部循环至少运行array.length / 2次,因此:
T >= (N/2)*(N/2)
i.e.,
T >= N²/4
这是O(N²)。但是,对于所有 array.length外部迭代,内部循环最多运行 array.length次,所以:
T <= N*N, i.e.,
T <= N²
这也是O(N²)。由于我们的时间上限和下限均为O(N²),因此我们知道T在O(N²)中。
注意:从技术上讲,我们只需要上限来表明T在O(N²)中,但我们通常会寻找尽可能紧的边界。 T实际上是Ө(N²)。
另请注意:上面使用 half 并没有什么特别之处 - 任何常数比例都可以。这些是一般规则:
下限:如果至少Ω(N)工作至少Ω(N)次,则表明您正在进行Ω(N²)工作。 Ω(N)*Ω(N)=Ω(N²)
上限:如果你最多O(N)工作最多O(N)次,你正在进行O(N²)工作。 O(N)* O(N)= O(N²)
由于我们都有,我们可以使用:Ω(N²)∩O(N²)=Ө(N²)