算法_复杂度分析(上)

195 阅读3分钟

学习算法避不开复杂度分析,所以记录一下复杂度分析的方方面面,这篇记录基础知识。


一、为什么要用估算这种方式

分析算法复杂度,一般用BigO复杂度表示法,为什么不用机器来统计呢?原因有二:

  1. 机器硬件参数的不同,影响统计结果;
  2. 测试数据的规模大小,也会影响结果。

而BigO的估算特点,恰好可以忽视上面两条具体因素,间接做到统一标准。

二、Big O时间复杂度表示法

Big O表示的是正相关。这里指的则是:

代码总运行时间T(n)与每行代码执行次数f(n)成正比

公式为:T(n) = O(f(n))

当然T(n),f(n)不是具体的执行时间,而是:

代码执行时间随数据规模增长的变化趋势,所以,也叫作渐进时间复杂度(asymptotic time complexity),简称时间复杂度。

因此,随着数据规模变大,Big O看重的是f(n)里参数的最大量级,而低阶、常量、系数相对来说不影响总量,所以忽略。

如果f(n)参数为2n的二次方+2n+3 ,其中最大量级是n的2次方,那么n和其他常数、系数都忽略不计,这段复杂度就为:

T(n) = O(n2)

三、怎么分析时间复杂度

方法一:只看循环执行次数最多的那段代码

由于BigO看重的是f(n)里参数的最大量级,忽略低阶、常量、系数。而一段代码中,往往是循环次数最多的那一段代码量级最大,因此这段代码的量级就是要分析的时间复杂度。

方法二:加法法则,取相加后复杂度最大的那个

如果有三段代码,我们要估算这三段代码整体的时间复杂度。

第一段代码是一个常量:1000次,因此忽略。

值得注意的是就算这个常量很大,但也忽略。

尽管这会对代码的执行时间有很大影响,但是回到时间复杂度的概念来说,它表示的是一个算法执行效率与数据规模增长的变化趋势,所以不管常量的执行时间多大,我们都可以忽略掉。因为它本身对增长趋势并没有影响。

第二段代码的时间复杂度是O(n)。

第三段代码的时间复杂度是O(n2)。

这三段复杂度相加:

T(n) = n2 + n + 1000

其中n2最大,保留,忽略其他,所以最终复杂度为O(n2)。

方法三:乘法法则,嵌套代码的复杂度=嵌套内外代码复杂度的乘积

反映在代码里,则是嵌套的循环。

如果外面的循环复杂度是O(n),里面的同样是O(n),那么总的复杂度就是:

T(n) = O(n * n) = O(n2)

四、常见的复杂度量级

(按从低到高排序)

多项式量级:

  • 常量级 O(1)
  • 对数级 O(logn)
  • 线性级 O(n)
  • 线性对数级 O(n)
  • 平方级 O(n2)
  • 立方级 O(n3)
  • K次方级 O(nk)

非多项式量级:

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

五、总结

还有空间复杂度,不过分析思路和时间复杂度一样。

可以看到复杂度分析并不难,关键还是多练习运用。