事后统计法干扰因素多,例如处理器速度、测试数据规模等。因此采用复杂度分析。
一、时间复杂度
1.大O时间复杂度表示法
大O表示代码执行时间随数据规模增长的变化趋势,所以叫渐进时间复杂度(asymptotic time complexity)。所有代码的执行时间T(n)与每行代码的执行次数成正比,即大O时间复杂度表示法: T ( n ) = O ( f ( n ) ) T(n) = O(f(n)) T(n)=O(f(n)),其中 f ( n ) f(n) f(n)表示每行代码执行次数总和。例如:
int cal(int n) {
int sum = 0;
int i = 1;
int j = 1;
for (; i <= n; ++i) {
j = 1;
for (; j <= n; ++j) {
sum = sum + i * j;
}
}
}
第2、3、4行 = 3;第5、6行 = 2n;第7、8行 = 2 n 2 2n^2 2n2;因此上面代码 T ( n ) = ( 2 n 2 + 2 n + 3 ) ∗ u n i t T i m e T(n) = (2n^2+2n+3)*unitTime T(n)=(2n2+2n+3)∗unitTime. 利用公式, T ( n ) = O ( 2 T(n) = O(2 T(n)=O(2n^2 + 2 n + 3 ) +2n+3) +2n+3)。
只记录最大量级,即 T ( n ) = O ( n 2 ) T(n) = O(n^2) T(n)=O(n2)。其中嵌套循环复杂度是嵌套内外代码复杂度的乘积。
2.量级排序
O
(
1
)
<
O
(
l
o
g
(
n
)
)
<
O
(
n
)
<
O
(
n
l
o
g
(
n
)
)
<
O
(
n
k
)
<
O
(
2
n
)
<
o
(
n
!
)
O(1)<O(log(n))<O(n)<O(nlog(n))<O(n^k)<O(2^n)<o(n!)
O(1)<O(log(n))<O(n)<O(nlog(n))<O(nk)<O(2n)<o(n!)
其中
O
(
2
n
)
O(2^n)
O(2n)和
o
(
n
!
)
o(n!)
o(n!)为非多项式量级(Non-Deterministic Polynomial)。
(1) O ( l o g ( n ) ) O(log(n)) O(log(n))
其中 O ( l o g ( n ) ) O(log(n)) O(log(n))举例,下面代码执行次数 x x x, 2 x = n 2^x = n 2x=n, 即为 O ( l o g 2 n ) O(log_2n) O(log2n):
i=1;
while (i <= n) {
i = i * 2;
}
(2) O ( m + n ) O(m+n) O(m+n)
代码中有两个数据规模。
二、空间复杂度
渐进空间复杂度(asymptotic space complexity),表示算法的存储空间与数据规模之间的增长关系。
看的是申请空间存储变量的规模。常见为
O
(
1
)
,
O
(
n
)
,
O
(
n
2
)
O(1),O(n),O(n^2)
O(1),O(n),O(n2)。
三、最好、最坏、平均和均摊情况时间复杂度
下面代码最好情况时间复杂度为
O
(
1
)
O(1)
O(1),最坏为
O
(
n
)
O(n)
O(n)。
平均时间复杂度应该计算为加权平均时间复杂度,用概率论的方法,
O
(
(
3
n
+
1
)
/
4
)
O((3n+1)/4)
O((3n+1)/4)。
// n表示数组array的长度
int find(int[] array, int n, int x) {
int i = 0;
int pos = -1;
for (; i < n; ++i) {
if (array[i] == x) {
pos = i;
break;
}
}
return pos;
}
均摊时间复杂度即将耗时多的操作均摊到耗时少的操作中,一般情况下这个值等于最好情况时间复杂度。
例如:
// 全局变量,大小为10的数组array,长度len,下标i。
int array[] = new int[10];
int len = 10;
int i = 0;
// 往数组中添加一个元素
void add(int element) {
if (i >= len) { // 数组空间不够了
// 重新申请一个2倍大小的数组空间
int new_array[] = new int[len*2];
// 把原来array数组中的数据依次copy到new_array
for (int j = 0; j < len; ++j) {
new_array[j] = array[j];
}
// new_array复制给array,array现在大小就是2倍len了
array = new_array;
len = 2 * len;
}
// 将element放到下标为i的位置,下标i加一
array[i] = element;
++i;
}
上面例子,最好情况时间复杂度为 O ( 1 ) O(1) O(1),最坏为 O ( n ) O(n) O(n),均摊为 O ( 1 ) O(1) O(1)。