四个时间复杂度分析方法
同一段代码在不同输入的情况下,可能存在时间复杂度量级不一样的情况,所以有以下四种不同的时间复杂度。
最好情况时间复杂度(best case time complexity);
最坏情况时间复杂度(worst case time complexity);
平均情况时间复杂度(average case time complexity);
均摊时间复杂度(amortized time complexity)。
概念理解
1、最好、最坏、平均情况时间复杂度
举例:
// 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;
}
这是一个find()函数,这段代码的作用是查找参数x在数组array中的位置,如果没有就返回-1。
最好情况时间复杂度:
在最理想的情况下,代码的时间复杂度。本例中,如果数组中的第一个元素就是要查找的变量,则时间复杂度为O(1)。最坏情况时间复杂度:
在最糟糕的情况下,代码的时间复杂度。本例中,如果数组中没有变量x,则需要遍历数组中的每一个元素,则时间复杂度为O(n)。-
平均情况时间复杂度:
最好、最坏情况时间复杂度表示的都是代码在极端情况下的时间复杂度,发生的概率并不大,所以平均情况时间复杂度用于表示平均情况下的时间复杂度。本例中,首先,变量x分为在数组中和不在数组中两种情况,假设两种情况的概率相同为
;其次,要查找的变量出现在数组0 ~ n-1共n个位置的概率是一样的,都为
;最后,根据概率论的知识,变量x出现在0 ~ n-1这n个位置的概率都为
,变量不在数组中的概率为
。
根据概率论中的加权平均值,也叫期望值的计算放法(每一种情况下的时间复杂度乘以其发生的概率)得出平均时间复杂度的值:
用大O表示法表示,则平均时间复杂度为O(n),所以平均时间复杂度又叫加权平均时间复杂度,或者期望时间复杂度。
一般情况下,我们并不会区分这三种时间复杂度,只使用其中一种即可。当同一代码块在不同情况下的时间复杂度有量级上的差距,才会区分这三种复杂度。
2、均摊时间复杂度
由上述可知,一般情况下,并不区分最好、最坏、平均情况时间复杂度,平均情况时间复杂度也只有在某些特殊的情况下才会使用,而均摊时间复杂度的应用场景比平均复杂度更特殊,更有限。
举例:
// array表示一个长度为n的数组
// 代码中的array.length就等于n
int *array = new int[n];
int count = 0;
void insert(int val) {
if (count == array.length) {
int sum = 0;
for (int i = 0; i < array.length; ++i) {
sum = sum + array[i];
}
array[0] = sum;
count = 1;
}
array[count] = val;
++count;
}
这是一个insert()函数,实现往数组中插入一个数据的功能,如果数组满了的话,即当count == array.length
时,遍历数组求和,并把数据放到数组第一个位置,然后再把新的数据插入。
1)、最好、最坏、平均情况时间复杂度
本段代码的时间复杂度分析:
- 最好情况时间复杂度:数组未满,有空闲的位置时为O(1);
- 最坏情况时间复杂度:数组已满,需要遍历求和时为O(n);
- 平均情况时间复杂度:分为数组未满和已满两种情况,未满时的插入有n种情况,每种情况的时间复杂度为O(1),已满时的时间复杂度度为O(n),所以共n+1种可能,这n+1种可能的概率相同都是
,所以平均情况时间复杂度为:
2)、均摊时间复杂度
本例中的insert()函数区别于之前的find()函数:find()函数在极端情况下,时间复杂度为O(1),而insert()函数在大多数情况下时间复杂度都为O(1);find()函数时间复杂度的多种情况并没有任何规律。而insert()函数O(n)之后,必有n-1个O(1),循环往复。
针对这种特殊的场景,可以采用一种特殊的时间复杂度分析方法:摊还分析法,得出的是均摊时间复杂度。
分析方法:
因为时间复杂度有规律的在O(n) -> n-1个O(1)之间循环,所以把耗时最多的那次操作(O(n)),均摊到耗时最少的n-1次操作(O(1)),这样,每一组操作的时间复杂度都是O(1),即均摊时间复杂度为O(1)。-
应用场景:
均摊时间复杂度就是一种特殊的平均情况时间复杂度,没有必要过度区分。当大部分情况下的时间复杂度较低,而只有极少数情况下的时间复杂度较高,且这些情况的出现有固定的时序性规律时,使用均摊时间复杂度。这时,尝试将较高复杂度操作的耗时均摊到较低复杂度的操作上,这就叫摊还分析法。一般能应用摊还分析法的场景,均摊时间复杂度就等于最好情况时间复杂度