复杂度分析
对于算法执行的时间和空间的分析,通过分析可以衡量算法的执行效率。
事后统计法
通过统计、监控得到算法执行的时间和占用的内存大小
局限性
- 测试结果依赖于测试环境
- 测试结果受数据规模的影响比较大
大 O 复杂度表示法
代码的执行时间 T(n) 与每行代码的执行次数 n 成正比
1 | T(n) = O(f(n)) |
大 O 时间复杂度表示法 表示代码执行时间随数据规模增长的变化趋势,也叫渐进时间复杂度,简称时间复杂度。
例如:假设每行代码的执行时间是 unitTime
且每行代码的执行时间相同,则下面代码的执行总时间是 $(2n + 2) * unitTime$ 即 $T(n) = O(2n + 2)$,当 n 趋近于无穷大时,则用量级表示即可:$T(n) = O(n)$,如果是双层循环则是:$T(n) = O(n^2)$
1 | int cal(int n) { |
时间复杂度分析
分析方法
- 关注循环执行次数最多的一段代码
- 加法法则:总复杂的等于量级最大的那段代码的复杂度
- 乘法法则:嵌套代码的复杂度等于嵌套内外代码复杂度的乘机
常见复杂度量级
- 常量阶 $O(1)$
- 对数阶 $O(logn)$
- 线性阶 $O(n)$
- 线性对数阶 $O(nlogn)$
- k 次方阶 $O(n^2)$ $O(n^3)$…$O(n^k)$
- 指数阶 $O(2^n)$
- 阶乘阶 $O(n!)$
非多项式量级:$O(2^n)$ 和 $O(n!)$,其他的是多项式量级,非多项式量级的算法问题叫做 NP (Non-Deterministic Polynomial)
非确定多项式问题
空间复杂度分析
空间复杂度是算法的存储空间与数据规模之间的增长关系,也叫做渐进空间复杂度
复杂度分析补充
最好情况时间复杂度
在理想的情况下执行代码的时间复杂度;例如下面代码的最好情况时间复杂度是:$O(1)$
1 | // n 表示数组 array 的长度 |
最坏情况时间复杂度
在最糟糕的情况下执行代码的时间复杂度;例如上面代码的最坏情况时间复杂度是:$O(n)$
平均情况时间复杂度
将每种情况出现的概率考虑进去,例如上面的代码:要查找的数据出现在数组中和不出现在数组中的概率是$1/2$,出现在 0~n-1 这 n 个位置的概率是 $1/n$,则要查找的数据可能出现在数组中的概率是:$1/2n$,将每种情况发生的情况考虑进去就是,去掉系数常量就是 $O(n)$
$$
1\frac{1}{2n} + 2\frac{1}{2n}+…+n\frac{1}{2n}+n\frac{1}{2}=\frac{n(n+1)}{4n}+\frac{n}{2}=\frac{3n+1}{4}
$$
均摊时间复杂度
对一个数据结构的一组操作中,大部分情况下耗时都很低,个别情况比较高,并且这些操作存在前后连贯的时序关系,可以将这一组操作放在一块儿分析,将高耗时的分摊到其他情况中。