一、什么是复杂度分析
- 什么是数据结构与算法:算法是作用在特定的数据结构之上的一系列数据操作,算法与数据结构是一体两面不可分割
- 复杂度分析:针对算法的分析,企图分析数据规模和对应算法消耗空间+时间的量化关系
二、复杂度分析意义
- 复杂度分析可以很快得出,不同算法在效率和性能上的差异
- 复杂度分析是一种事前分析方法,给开发者提供一个算法优劣的评判标准。在实际开发中,除关注算法复杂度外还需要综合考虑其他各种因素,例如:cpu cache、业务特殊性、操作便利性…
- 有些开发者倾向于直接把代码跑一遍观察耗时,这种属于事后分析法,这种分析方法是有局限性的,1)硬件配置不用结果差别很大 2)样本不同可能导致结果差别大
三、如何分析复杂度
- 假设前提:假设每一行代码执行时间都相同,称之为单位时间unit_time
- 计算耗时:程序一共执行了多少行代码,可得到耗费了多少个单位时间,例如下面代码,耗时T(n) = (2n + 2) × unit_time
- 大O表示法:T(n) = O( f(n) ) = O(2n + 2),其中n表示数据规模,f(n)表示代码执行的总行数,抽象T(n)、f(n)呈正相关
- 大O表示法,也是大O时间复杂度表示法,简称时间复杂度
- 注意:由于复杂度分析涉及到的数据规模较大,分析时候会对表达式做适当简化,即简化f(n),只关注到f(n)中会引起绝对变化的部分:
- 执行次数最多的一段代码,例如:f(n) = 2n + 2,简化为:f(n) = n
- 加法法则
- 乘法法则
function example ($n) {
$sum = 0;
for($i=0; $i<$n; ++$i)
$sum += $i;
return $n;
}
四、常见的复杂度
常数阶
线性阶
对数阶
平方阶
指数阶
阶乘阶
五、其他
- 最好时间复杂度、最坏时间复杂度、平均时间复杂度、均摊时间复杂度
function search ($array, $len, $target) {
$index = -1;
for($i=0; $i<$len; ++$i){
if($array[$i] == $target)
return $index = $i;
}
return $index;
}
- 分析以上代码
- 最好时间复杂度:当target在数组第一个顺位,时间复杂度O(1)
- 最坏时间复杂度:当target在数组最后一位,或者不在数组中,时间复杂度O(n)
- 平均时间复杂度:加权平均计算O(n)
- target有1/2机会不在数组中,不在数组中时间复杂度为O(n)
- target在数组中,则会有n种情况,不同情况下遍历次数不同
- 加权平均期望:n×1/2 + 1×1/2n + 2×1/2n + 3×1/2n +…+ n×1/2n = (3n+1)/4
- 均摊时间复杂度:均摊时间复杂度用到摊还分析方法。
- 摊还分析法适用场景:复杂度有规律地变动,多次低复杂度情况下跟着一个高复杂度情况,就考虑可以把复杂度高的情况分摊到其他复杂度简单的情况,均摊时间复杂度本质上还是平均时间复杂度,只不过换了一个角度来理解,均摊时间复杂度为最好时间复杂度