复杂度O
数学公式
O(g(n)) = {f(n): There exist positive constants c and n0 such that 0≤f(n) ≤cg(n) for all n≥n0}
解释
对于所有的n≥n0,其中n0>0,存在正常数c,有0≤f(n) ≤cg(n) ,则我们说算法的复杂度为O(g(n))。(一般取最坏情况下的复杂度即可,或者大于也可以)
应用
- O复杂度表示一个算法复杂度的上界。
- O复杂度一般代表算法的最坏情况的时间复杂度,但是最好情况下算法复杂度可能会更好。
- O复杂度更容易去分析算法
e.g.
k1n2+k2n+k3∈O(n3)
proof(用定义证明)
k1n2 + k2n+ k3≤(|k1|+|k2|+|k3|)n3
(一般直接往大了取,这里也可以是O(n2),一般越精确越好)
复杂度Ω
数学公式
Ω(g(n)) = {f(n): There exist positive constants c and n0 such that 0 ≤ cg(n) ≤f(n) for all n≥n0}
解释
对于所有的n≥n0,其中n0>0,存在正常数c,有0 ≤ cg(n) ≤f(n) ,则我们说算法的复杂度为O(g(n))。(一般取最好情况下的复杂度即可,或者小于也可以)
应用
- Ω复杂度代表一个算法复杂度的下界。
- Ω复杂度一般表示一个算法的最好情况下的时间复杂度,最坏情况下复杂度可能会更差。
e.g.(可以低于,但是不能大于)
k1n2+k2n+k3∈Ω(n2)
k1n2+k2n+k3∈Ω(n)
复杂度θ
数学公式
Θ(g(n)) = {f(n): There exist positive constants c1, c2, and n0 > 0 such that 0≤c1g(n) ≤f(n)≤c2g(n) for all n≥n0}
解释
对于所有的n≥n0,其中n0>0,存在两个正常数c1, c2, 使得0≤c1g(n) ≤f(n)≤c2g(n)成立,那么我们就说这个算法的复杂度是θ(g(n))
应用
- θ(.)更能够准确的表示一个算法的复杂度。
- 一般我们说一个算法的复杂度为θ(g(n)),有且只有f(n) = O(g(n)) 且f(n) = Ω(g(n))
化简
丢掉低阶次项(low-order terms);
忽略前导常数(leading constants);(最高次项前的常数)
e.g.
3n3 + 90n2 – 5n + 6046 = Θ(n3)
注意(f(n)代表算法的真实复杂度)
- 一般我们认为f(n) = O(g(n)) 对应于f(n)≤g(n)
- f(n) = Θ(g(n)) 对应于 f(n) = g(n)
- f(n) = Ω(g(n)) 对应于 f(n) ≥ g(n)
算法复杂度的求解
一般方法
- 数学归纳
- 公式推导
- 画出递归树(对于递归)
对于复杂度程序的复杂度求解
T(n)=aT(n/b)+D(n)+C(n)
e.g. T(n)=2T(n/2)+θ(n)
对于递归算法复杂度求解方法
- 替换法
- 递归树
- 主方法(很重要)
替换法
有两种方法:
-
简单来说就是通过猜O上界和Ω下界来确定复杂度θ
第一步:猜复杂度的形式
第二步:通过推导验证
第三步:解决常数问题
e.g. T(n) = 4T(n/2) + 100n
Assume that T(1) = Θ(1)
Guess O(n3). (Prove O and Ω separately for Θ)
Assume that T(k) ≤ck3for k < n
Prove T(n) ≤cn3 by induction(归纳法证明)
Ω类似
注意:一定要符合Ω和O的原始定义 -
往我们熟悉的算法复杂度上面推导
e.g. T(n) = 2T(n1/2) + lgn,
令m=lgn,T(2m) = 2T(2m/2) + m.
令S(m) = T(2m),S(m) = 2S(m/2) + m (和归并排序的复杂度类似) ===> S(m) = O(mlgm)
把S(m)代回T(n), T(n) = T(2m) = S(m) = O(mlgm) = O(lgnlglgn)
递归树
递归树为递归算法建模。
递归树适用于替换法的猜想部分。
递归树是不可靠的,仅仅提升了对算法的复杂度的一个直觉。
e.g. T(n) = 3T(n/4) + Θ(n2)
主方法
为解决T(n) = a T(n/b) + f(n)的递归算法计算复杂度提供了一个很好的方法。(a,b都为常数,a>=1 && b>1,f(n)为渐进的正函数)
第一步:画出递归树
n=bL -> L=logbn
alogbn=nlogba
所以最后一层为: nlogba T(1)
第二步:比较叶子和根的复杂度的增加速率
- f(n) = O(nlogba-ε) 其中ε>0,ε是n的指数
f(n)比叶子nlogba增长的慢
所以T(n)=θ(nlogba) - f(n) = Θ(nlogbalgkn) 其中k>=0的常数
f(n)和nlogba增长速率相同(lgkn可以相当于一个常数,尤其k=0)
所以T(n)=θ(nlogbalgk+1n)
最后k+1的原因是因为有lgn层结点 - f(n) = Ω(nlogba+ε) 其中ε>0,是n的指数
f(n)比叶子nlogba增长的快,且满足af(n/b) ≤cf(n)(即每层的结点的复杂度是递减的)
所以T(n)=θ(f(n))
习题
T(n)=9T(n/3)+n
answer: θ(n2)
T(n)=T(2n/3)+1
answer:θ(lgn)
T(n)=3T(n/4)+nlgn
answer:θ(nlgn)
(算法萌新一枚,如有不对,还请指正)