数据结构与算法系列—最好、最坏、平均、摊还时间复杂度
实例代码
在数组array中查询元素x的下标。
// 在数组array中查询元素x的下标。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;
}
最好、最坏时间复杂度
最好情况时间复杂度就是,在最理想的情况下,执行这段代码的时间复杂度。
最坏情况时间复杂度就是,在最糟糕的情况下,执行这段代码的时间复杂度。
上面这段代码中,最好的情况是在数组的第一个元素就找到x,所以最好时间复杂度是O(1)。
最糟糕的情况是在数组的最后一个元素才找到x,所以最坏时间复杂度是O(n)。
平均时间复杂度
上面这段代码,要查找的变量x在数组中的位置,有n+1种情况:在数组的0~n-1位置中和不在数组中。
我们把每种情况下,查找需要遍历的元素个数累加起来,然后再除以n+1,就可以得到需要遍历的元素个数的平均值,即:
(1 + 2 + ... + n + n)/ (n + 1) = n(n + 3) / 2(n + 1)
时间复杂度的大O标记法中,可以省略掉系数、低阶、常量。
所以,这个公式简化之后,得到的平均时间复杂度就是O(n)。
摊还时间复杂度
在下面这段代码中,只有在某种特殊的情况,即i >= len时,时间复杂度才是O(n)。
一般情况下的时间复杂度时O(1)。特殊情况下的时间复杂度可以分摊到每一个一般情况下。
因此,摊还时间复杂度为O(1)。
// 全局变量,大小为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;
}