1.有些特殊场景会用到下面几个时间复杂度
最好、最坏、平均、均摊时间复杂度
2.概念介绍
最好情况时间复杂度:在最理想的情况下,执行这段代码的时间复杂度。
最坏情况时间复杂度:在最糟糕的情况下,执行这段代码的时间复杂度。
平均情况时间复杂度:最好和最坏时间两个极端情况,并不能描述一般情况。所以来了个平均的。
均摊情况时间复杂度:一种特殊的平均情况时间复杂度。可以用简单的摊还分析法得出。
3.举个例子
3.1 平均时间复杂度
查找某个元素是否在数组中,如果在就返回下表。
// n 即数组array的长度
int get(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;
}
最好情况第一个就是时间复杂度为O(1),最坏的就是遍历完整个数组,O(n)
平均情况时间复杂度,分析下,查找元素X,可能是在0到n-1 的某个位置或者不在数组中。直接把遍历元素加起来除以n+1.
忽略系数,低阶,常量。平均时间复杂度为O(n)
换一种比较简单的分析方法,在不在数组中的概率为1/2 。在0~n-1个位置,被查找元素的出现的概率为1/n。根据概览乘法规则,在0到n-1中,任意一个位置出现的概览为1/2n。
最后一项,n/2,我的理解就是元素没在数组中情况的概率。不在数组中的概率1/2,n种情况。
综上,平均时间复杂度为O(n)
3.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;
}
如果按照平均时间复杂度的分析方法,有空闲的时候,插入,时间复杂度为O(1)没有空闲,时间复杂度为O(n)
每种情况发生的概览为 1/n+1,加权平均计算方法,求得平均时间复杂度。
n个O(1),最后一个是O(n)
换一种简单的分析方法,摊还分析法。
每一次O(n)的操作之后,都会伴随着n-1次O(1)的操作,如果把O(n)耗时多的操作,均摊到n-1次耗时少的操作上,这样均摊下来。均摊时间复杂度就为O(1)了。
参考资料:《数据结构与算法之美》