最好、最坏情况时间复杂度

  • 最好情况时间复杂度就是,在最理想的情况下,执行这段代码的时间复杂度
  • 最坏情况时间复杂度就是,在最糟糕的情况下,执行这段代码的时间复杂度

平均情况时间复杂度

要查找的变量 x 在数组中的位置,有 n+1 种情况:在数组的 0~n-1 位置中和不在数组中。我们把每种情况下,查找需要遍历的元素个数累加起来,然后再除以 n+1,就可以得到需要遍历的元素个数的平均值,即:

  • O(n)

image.png

为了方便你理解,我们假设在数组中与不在数组中的概率都为 1/2。另外,要查找的数据出现在 0~n-1 这 n 个位置的概率也是一样的,为 1/n。所以,根据概率乘法法则,要查找的数据出现在 0~n-1 中任意位置的概率就是 1/(2n)。

我们把每种情况发生的概率也考虑进去,那平均时间复杂度的计算过程就变成了这样:

image.png

这个值就是概率论中的加权平均值,也叫作期望值,所以平均时间复杂度的全称应该叫加权平均时间复杂度或者期望时间复杂度。

只有同一块代码在不同的情况下,时间复杂度有量级的差距,我们才会使用这三种复杂度表示法来区分。

均摊时间复杂度

  1. // array表示一个长度为n的数组
  2. // 代码中的array.length就等于n
  3. int[] array = new int[n];
  4. int count = 0;
  5. void insert(int val) {
  6. if (count == array.length) {
  7. int sum = 0;
  8. for (int i = 0; i < array.length; ++i) {
  9. sum = sum + array[i];
  10. }
  11. array[0] = sum;
  12. count = 1;
  13. }
  14. array[count] = val;
  15. ++count;
  16. }
  • 最好 O(1)
  • 最坏 O(n)
  • 平均 O(1)

操作次数*出现概率:

image.png

规律:

  • 一个 O(n) 插入之后,紧跟着 n-1 个 O(1) 的插入操作,循环往复
  • 通过摊还分析得到的时间复杂度我们起了一个名字,叫均摊时间复杂度。

每一次 O(n) 的插入操作,都会跟着 n-1 次 O(1) 的插入操作,所以把耗时多的那次操作均摊到接下来的 n-1 次耗时少的操作上,均摊下来,这一组连续的操作的均摊时间复杂度就是 O(1)。这就是均摊分析的大致思路。

  • (n + 1*(n-1))/n = 2

对一个数据结构进行一组连续操作中,大部分情况下时间复杂度都很低,只有个别情况下时间复杂度比较高,而且这些操作之间存在前后连贯的时序关系,这个时候,我们就可以将这一组操作放在一块儿分析,看是否能将较高时间复杂度那次操作的耗时,平摊到其他那些时间复杂度比较低的操作上。

而且,在能够应用均摊时间复杂度分析的场合,一般均摊时间复杂度就等于最好情况时间复杂度