7 时空复杂度分析
一般来说,c++
每秒钟可以算107~ 108 次
类型总结
yxc总 总结有:
[由数据范围反推算法复杂度以及算法内容](由数据范围反推算法复杂度以及算法内容 - AcWing):
一般ACM或者笔试题的时间限制是1秒或2秒。
在这种情况下,C++代码中的操作次数控制在107为最佳。
下面给出在不同数据范围下,代码的时间复杂度和算法该如何选择:
n≤30
, 指数级别, dfs+剪枝(暴力搜素),状态压缩dpn≤100
→ O(n3),floyd,dpn≤10^3
→ O(n2),O(n2logn),dp,二分n≤10^4
→ O(n∗√n) ,块状链表n≤10^5
→ O(nlogn) => 各种sort,线段树、树状数组、set/map、heap、dijkstra+heap、spfa、求凸包、求半平面交、二分n≤10^6
→ O(n), 以及常数较小的O(nlogn) 算法 => hash、双指针扫描、并查集、kmp、AC自动机,常数比较小的 O(nlogn) 的做法:sort、树状数组、heap、dijkstra、spfan≤10^7
→ O(n),双指针扫描、kmp、AC自动机、线性筛素数n≤10^9
→ O(√n),判断质数n≤10^18
→ O(logn),最大公约数
代码时间复杂度分析
主要是对递归代码的时间复杂度进行分析
-
纯循环
观察代码中的循环即可
-
递归算法
递归算法的时间复杂度本质上是 递归的次数 ***** 每次递归中操作的次数
-
使用递推方法求时间复杂度(也就是写出式子一个一个求就可以了)
-
主定理(Master Theorem)
if T ( n ) = a T ( [ n b ] ) + O ( n d ) T(n) = aT(\left[\frac{n}{b}\right])+O(n^d) T(n)=aT([bn])+O(nd) (for constants a > 0 , b > 1 , d ≥ 0 a>0,b>1,d \ge 0 a>0,b>1,d≥0), then:
T ( n ) = { O ( n d ) i f d > l o g b a O ( n d l o g n ) i f d = l o g b a O ( n l o g b a ) i f d < l o g b a T(n)=\left\{ \begin{aligned} O(n^d) ~~~ if~~d~>~log_b~a\\ O(n^d~log~n) ~~~ if~~d~=~log_b~a\\ O(n^{log_b~a}) ~~~ if~~d~<~log_b~a \end{aligned} \right. T(n)=⎩ ⎨ ⎧O(nd) if d > logb aO(nd log n) if d = logb aO(nlogb a) if d < logb a
其中,
n
是问题规模的大小,a
是原问题子问题的个数,n/b
是每个子问题的大小, O(nd) 是将原问题分解成子问题和将子问题的解合并成原问题的解的时间(这里O(n)d其实可以等价于写成f(n),然后就可以用 O ( n l o g b a ) O(n^{log_b~a}) O(nlogb a)和f(n)
进行比较了)。在这篇专栏中有一些例子:主定理(Master Theorem) - 知乎 (zhihu.com)
-
递归树
递归树的规则为:
(1) 每层的节点为
T(n) = kT(n / m) + f(n)
中的f(n)
在当前的n/m
下的值;(2) 每个节点的分支数为
k
;(3) 每层的右侧标出当前层中所有节点的和。
在这篇博客的文末有两个详细的例子:三种方法求递归算法的时间复杂度(递推,master定理,递归树)_毕业势必进大厂的博客-优快云博客_递归求时间复杂度
-