数据结构与算法笔记(二)复杂度分析

2. 复杂度分析

2.1 什么是复杂度分析

数据结构和算法的本质:快和省,如何让代码运行得更快、更省存储空间。

算法复杂度分为时间复杂度和空间复杂度,从执行时间和占用空间两个维度来评估数据结构和算法的性能。

复杂度描述的是算法执行时间(或占用空间)与数据规模的增长关系,越高阶复杂度的算法,执行效率越低。

2.2 为什么需要复杂度分析

如果采用性能测试,测试结果非常依赖测试环境和受数据规模的影响很大。而复杂度分析有不依赖执行环境、成本低、效率高、易操作、指导性强的特点。

2.3 如何进行复杂度分析

2.3.1 大O表示法

不是代码真正执行的时间,而是表示代码执行时间随数据规模增长的变化趋势,叫作渐进时间复杂度,简称时间复杂度。

T ( n ) = O ( f ( n ) ) T(n) = O(f(n))

T ( n ) T(n) 表示代码执行的时间; n n 表示数据规模的大小; f ( n ) f(n) 表示每行代码执行的次数总和; O O 表示代码的执行时间 T ( n ) T(n) f ( n ) f(n) 表达式成正比。

2.3.2 时间复杂度

  • 只关注循环执行次数最多的一段代码
  • 加法规则:总复杂度等于量级最大的那段代码的复杂度
  • 乘法规则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积
  • 代码复杂度由两个数据规模决定的,不能简单利用加法规则,复杂度为 O ( m + n ) O(m+n)

几种常见时间复杂度

  • 多项式量级:

    • 常量阶 O ( 1 ) O(1) :代码执行时间不随n的增大而增长
    • 对数阶 O ( l o g n ) O(log n)
    • 线性阶 O ( n ) O(n)
    • 线性对数阶 O ( n l o g n ) O(nlogn)
    • 平方阶 O ( n 2 ) O(n^2) 、立方阶 O ( n 3 ) O(n^3) \cdots k次方阶 O ( n k ) O(n^k)
  • 非多项式量级:当数据规模越来越大时,算法执行时间会急剧增加,非常低效

    • 指数阶 O ( 2 n ) O(2^n)
    • 阶乘阶 O ( n ! ) O(n!)

2.3.3 空间复杂度

渐进空间复杂度,表示算法的存储空间与数据规则之间的增长关系。

常见的空间复杂度:

  • O ( 1 ) O(1)
  • O ( n ) O(n)
  • O ( n 2 ) O(n^2)

2.4 时间复杂度情况

  • 最好情况时间复杂度(best case time complexity)

  • 最坏情况时间复杂度(worse case time complexity)

  • 平均情况时间复杂度(average case time complexity)

  • 均摊时间复杂度(amortized time complexity)

2.4.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;
}

如果要查找的变量x正好是数组的第一个元素,对应的时间复杂度即为最好情况时间复杂度。

2.4.2 最坏情况时间复杂度

在最糟糕的情况下,执行这段代码的时间复杂度。

以刚刚举的例子,如果数组中没有要查找的变量x,需要把整个数组都遍历一遍时,此时对应的时间复杂度即为最坏情况时间复杂度。

2.4.3 平均情况时间复杂度

也叫加权平均时间复杂度或期望时间复杂度,用代码在所有情况下执行的次数的加权平均值表示。

假设在数组中与不在数组中的概率都为 1 2 \frac{1}{2} ,且要查找的数据出现在 0~n-1 这 n 个位置的概率也是一样的,都为 1 n \frac{1}{n} 。因此,根据概率乘法法则,要查找的数据出现在 0~n-1 中任意位置的概率是 1 2 n \frac{1}{2n} 。那么平均情况复杂度的计算过程为:

1 × 1 2 n + 2 × 1 2 n + 3 × 1 2 n + + n × 1 2 n + n × 1 2 = 3 n + 1 4 1\times\frac{1}{2n} +2\times \frac{1}{2n} + 3\times \frac{1}{2n} + \cdots +n\times \frac{1}{2n} + n\times \frac{1}{2}=\frac{3n+1}{4}​

2.4.4 均摊时间复杂度

对一个数据结构进行一组连续操作中,大部分情况下时间复杂度都很低,只有个别情况下时间复杂度比较高,而且这些操作出现的频率是非常有规律的,之间存在前后连贯的时序关系。此时,就可以将这一组操作一起分析,将较高时间复杂度的那次操作的耗时,平摊到其他那些时间复杂度比较低的操作上。能够应用均摊时间复杂度分析的场合,一般均摊时间复杂度等于最好情况时间复杂度。

均摊时间复杂度应用的场景特殊、有限,可以看成一种特殊的平均时间复杂度。

2.4.5 总结

只有同一块代码在不同的情况下,时间复杂度有量级的差距,我们才会使用这几种复杂度表示法来区别。一般情况下,使用一个复杂度就可以满足需求。

猜你喜欢

转载自blog.csdn.net/weixin_43004311/article/details/84575172