algorithms 时间复杂度
参考链接
python 数据结构时间复杂度
列表
| 操作 | 平均情况 | 最坏情况 |
|---|---|---|
| copy | O(n) | O(n) |
| append | O(1) | O(1) |
| insert | O(n) | O(n) |
| 取元素 list[i] | O(1) | O(1) |
| 修改元素 | O(1) | O(1) |
| 删除元素 | O(n) | O(n) |
| 遍历 | O(n) | O(n) |
| 取切片 | O(k) | O(k) |
| 删除切片 | O(n) | O(n) |
| 修改切片 | O(n+k) | O(n+k) |
| extend | O(k) | O(k) |
| 排序 | O(n log n) | O(n log n) |
| 列表乘法 | O(nk) | O(nk) |
| x in s | O(n) | |
| min(s), max(s) | O(n) | |
| 计算长度 | O(1) |
集合
| 操作 | 平均情况 | 最坏情况 | |
|---|---|---|---|
| x in s | O(1) | O(n) | |
| 并集 s\ | t | O(len(s) + len(t)) | |
| 交集 s&t | O(min(len(s), len(t))) | O(len(s) * len(t)) | |
| 差集 s-t | O(len(s)) | ||
| s.difference_update(t) | O(len(t)) | ||
| 对称差集 s^t | O(len(s)) | O(len(s) * len(t)) | |
| s.symmetric_difference_update(t) | O(len(t)) | O(len(s) * len(t)) |
求差集 与 更新为差集的运算时间复杂度并不相同!
差集是生成新的集合,更新为差集是将t中的元素从s移除, 因此可以根据是否需要新集合来选择合适方法
字典
| 操作 | 平均情况 | 最坏情况 |
|---|---|---|
| copy | O(n) | O(n) |
| get | O(1) | O(n) |
| 更新 | O(1) | O(n) |
| 删除 | O(1) | O(n) |
| 遍历 | O(n) | O(n) |
实例分析
1. O(1)
- demo code
|
说明
上述三条单个语句的频度均为
1, 程序段的执行时间是与问题规模n无关的常数. 算法的时间复杂度为常数阶, 记作T(n) = O(1).
注意
如果算法的执行时间不随着问题规模
n的增加而增长, 即使算法中有上千条语句, 执行时间也不过一个较大的常数, 故此类算法的时间复杂度为O(1)
- 结论: $T(n) = O(1)$
2. O(n²)
$$
T(n) = O(n²)
$$
- demo code 1
|
解释
Θ(2n²+n+1)=n²(Θ即:去低阶项,去掉常数项,去掉高阶项的常参得到),所以T(n)==O(n²)
- 结论: $\Theta(2n^2 + n + 1) = n^2 {\rightarrow}T(n) = O(n^2)$
- demo code 2
|
说明
一般情况下, 只需要考虑循环体中语句的执行次数, 忽略终值判别, 控制转移等, 当由若干循环语句时, 算法的时间复杂度是由嵌套导数最多的循环语句中最内层语句的频度
f(n)决定的
3. O(n)
- demo code
|
- 说明
$$
T(n) = 3 + n + 2(n - 1) = 3n + 1 = O(n)
$$
4. O($log_2n$)
- demo code
|
说明
语句1频度为1
语句2为 f(n), 则 2^f(n) <= n; f(n) <= log~2~n
取最大值 f(n)=log~2~n结论: $T(n) = O(log_2n)$
5. O($n^3$)
- demo code
|
说明
简单可以认为
循环次数代表了时间复杂度O(n³)