3、复杂度分析

为什么需要复杂度分析?

把代码跑一遍,通过统计,监控得到算法执行时间和占用内存大小的方法叫做事后统计法,这种方法有以下局限性

  1. 测试结果非常依赖测试环境
    同一段代码拿到不同机子上测试会有不同的结果

  2. 测试结果受数据规模的影响很大

  3. 掌握复杂度分析,将能编写出性能更优的代码,有利于降低系统开发和维护成本。

综上,我们需要一个不用具体的测试数据来测试,就可以粗略地估计算法的执行效率的方法。所以就有了时间,空间复杂度分析方法

如何进行复杂度分析

大O复杂度表示法

时间复杂度(表示执行的快慢):

大O时间复杂度实际上并不具体表示真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势,也叫做渐进时间复杂度

T(n)=O(f(n))代码的执行时间跟每行代码执行次数的总和成正比
T(n)表示代码执行的时间,n表示数据规模的大小,f(n)表示每行代码执行的次数总和,因为这是一个公式,所以用f(n)来表示。公式中的O表示代码的执行时间T(n)与f(n)表达式成正比。
当n很大时,你可以把它想象成10000,100000。大O这种复杂度表示方法只是表示一种变化趋势,而公式中的低价,常量,系数三部分并不左右增长趋势,所以都可以忽略。

评论一个算法好坏的时候 我们应该先看指标T(n) 如果两个算法的指标一样的或者判断不出哪个指标高或者低 这个时候再去判断系数

分析法则:
  1. 只关注循环执行次数最多的一段代码

  2. 加法法则:总复杂度等于量级最大的那段代码的复杂度
    注意:只要是常量级的执行时间,不管这个常量是10000,100000 都可以忽略掉,时间复杂度表示的是一个算法的执行效率与数据规模增长的变化趋势,常量可以忽略掉的原因是它对增长趋势并没有影响
    T1(n)=O(f(n)), T2(n)=O(g(n)),那么T(n)=T1(n)+T2(n)=max(O(f(n)),O(g(n)))=O(max(f(n),g(n))).

  3. 乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘积,我们可以把乘法法则看成是嵌套循环
    T1(n)=O(f(n)), T2(n)=O(g(n)),那么T(n)=T1(n)*T2(n)=O(f(n))*O(g(n)) =O(f(n)*g(n)).

4.多个规模求加法:比如方法有两个参数控制两个循环的次数,那么这时就取二者复杂度相加
当数据规模无法评估哪个量级较大时,加法法则失效,可以使用O(m+n)

常用的复杂度级别:

在这里插入图片描述
在这里插入图片描述

非多项式量级:

随着数据规模的增长,算法的执行时间和空间占用暴增,这类算法性能极差
O(2n)和O(n!)

多项式量级:

随着数据规模的增长,算法的执行时间和空间占用,按照多项式的比例增长。

  1. O(1)常量级时间复杂度
    这里并不是说O(1)只执行了一行代码
    O(1)表示只要代码的执行时间不随n的增大而增大,这样代码的时间复杂度我们都计作O(1)。一般情况下,只要算法中不存在循环语句,递归语句,即使有成千上万的代码,其时间复杂度也是O(1)

2.O(logn),O(nlogn)
不管对数阶的底为多少,时间复杂度都为O(logn)。比如:log3n就等于log3nlog2n(换底公式),所以O(log3n)=O(Clog2n),其中C=log32是一个常量,我们知道,在采用大O标记复杂度的时候,可以忽略系数,即O(Cf(n))=O(f(n)).所以,O(log2n)就等于O(log3n)。因此,在对数阶时间复杂度的表示方法里,我们忽略对数的”底”,统一表示为O(logn)

O(nlogn)就是来自乘法法则。

3.O(m+n),O(m*n)

空间复杂度分析(表示内存的消耗):

表示算法的存储空间与数据规模之间的增长关系,也称为渐进空间复杂度
我们说空间复杂度的时候,是指除了原本的数据存储空间外,算法运行还需要额外的存储空间。

复杂度分析的4个概念
  1. 最好情况时间复杂度:
    代码在最理想情况下执行的时间复杂度。
  2. 最坏情况时间复杂度:
    代码在最坏情况下执行的时间复杂度。
  3. 平均情况时间复杂度(加权平均时间复杂度或者期望时间复杂度):
    用代码在所有情况下执行的次数的加权平均值表示。
  4. 均摊时间复杂度:
    在代码执行的所有复杂度情况中绝大部分是低级别的复杂度,个别情况是高级别复杂度且发生具有时序关系时,使用摊还分析(平摊分析)方法,可以将个别高级别复杂度均摊到低级别复杂度上。基本上均摊结果就等于低级别复杂度。

二、为什么要引入这4个概念?
1.同一段代码在不同情况下时间复杂度会出现量级差异,为了更全面,更准确的描述代码的时间复杂度,所以引入这4个概念。
2.代码复杂度在不同情况下出现量级差别时才需要区别这四种复杂度。大多数情况下,是不需要区别分析它们的。

三、如何分析平均、均摊时间复杂度?
1.平均时间复杂度
代码在不同情况下复杂度出现量级差别,则用代码所有可能情况下执行次数的加权平均值表示。
2.均摊时间复杂度
两个条件满足时使用:1)代码在绝大多数情况下是低级别复杂度,只有极少数情况是高级别复杂度;2)低级别和高级别复杂度出现具有时序规律。均摊结果一般都等于低级别复杂度。

总结:其实平均和平摊基本就是一个概念,平摊是特殊的平均

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章