算法复杂度

复杂度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)

对于递归算法复杂度求解方法

  • 替换法
  • 递归树
  • 主方法(很重要)

替换法

有两种方法:

  1. 简单来说就是通过猜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的原始定义

  2. 往我们熟悉的算法复杂度上面推导
    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)

第二步:比较叶子和根的复杂度的增加速率

  1. f(n) = O(nlogba-ε) 其中ε>0,ε是n的指数
    f(n)比叶子nlogba增长的慢
    所以T(n)=θ(nlogba)
  2. f(n) = Θ(nlogbalgkn) 其中k>=0的常数
    f(n)和nlogba增长速率相同(lgkn可以相当于一个常数,尤其k=0)
    所以T(n)=θ(nlogbalgk+1n)
    最后k+1的原因是因为有lgn层结点
  3. 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)


(算法萌新一枚,如有不对,还请指正)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值