前言
上一章中,做了复杂度分析的大部分知识的笔记:大O表示法以及相关的分析技巧,今天继续学习复杂度分析的其他知识。
四个复杂度分析
1.最坏情况时间复杂度:代码在最坏情况下执行的时间复杂度。 2.最好情况时间复杂度:代码在最理想情况下执行的时间复杂度。 3.平均时间复杂度(加权平均时间复杂度):代码在所有情况下执行次数的加权平均值表示的时间复杂度。 4.均摊时间复杂度:在代码执行的所有复杂度情况中绝大部分是低级别的复杂度,个别情况是高级别复杂度且发生具体时序关系时,可以将个别高级别复杂度均摊到低级复杂上。基本上均摊结果就等于低级复杂度。
为什么引入这些概念
先举一个查找元素的例子:
void method(int [] array, int s) {
// array是一个大小为n的数组
int count = -1;
for(int i = 0;i < array.length; i ++) {
if(array[i] == x) {
count = i;
break;
}
}
return count;
}
复制代码
可以看出,有可能执行1次就找到了,有可能需要执行n次就找到了,还有可能执行了 n+1 次没有找到。这个时候就需要上面的四个复杂度进行分析了。
代码复杂度在不同情况下出现量级差别时,才需要区别这四种情况,大多数情况下,是不需要区别分析它们的。
可以得出,最好情况时间复杂度为O(1),最坏情况时间复杂度为O(n)。那么平均复杂度和均摊复杂度又是什么呢?
如何进行平均、均摊复杂度分析
1.平均时间复杂度 代码在不同情况下的平均时间复杂度,用代码所有可能情况下执行次数的加权值表示。 在上述例子中,假如,出现在数组中和不出现在数组中的概率是对等的,每个都是1/2,0~n-1的概率也是相等的,就是1/n,那么每种情况就是 1/2n,那么就有了下面的公式:
1 * 1/2n + 2 * 1/2n ··· n * 1/2n = (3n +1)/4
复制代码
用大O表示法,就是O(n)
- 均摊时间复杂度 这种情况比平均时间复杂度的场景更加的特殊,可以将均摊时间复杂度理解为一种特殊的平均时间复杂度。就是将高级的复杂度均摊到低级的复杂度上。
int [] array = new int [n]
void insert (int x, int s) {
if(x >= n) {
int [] array1 = new int [x + 1]
for(int i = 0; i < n; i ++) {
array1[i] = array[i]
}
array1[x] = s;
return array1;
} else{
array[x] = s
return array
}
}
复制代码
分为两种 一种是 n >= x,执行一次,复杂度为O(1)。另一种 n < x,执行n次,复杂度为O(n).假如这 n+1次发生的概率一样,都是 1/n+1,
(1 * 1/n+1) + (1 * 1/n+1) + ... +(n * 1/n+1) = O(1)
复制代码
所以均摊复杂度为 O(1)