算法复杂度分析概要

一:渐近符号

1.1 符号的辨析

1.1.1 符号 O

  O,读作“大O”,非正式来说, O(g(n)) 是增长次数小于等于 g(n) 及其常数倍( n 趋向于无穷大)的函数集合。
  定义 如果函数f(n)包含在 O(g(n)) 中,记作 f(n)O(g(n)) (平时使用为了方便书写,我们通常使用 f(n)=O(g(n)) 代替)。它的成立条件是:对于所有足够大的 n f(n)的上界由 g(n) 的常数倍所确定,也就是说,存在大于0的常数 c 和非负整数n0,使得:

对于所有的 nn0 来说, f(n)c(g(n)

  下图说明了这个定义:

  下面给出几个例子:

n100n+512n(n1)n30.00001n3=O(n2)=O(n2)=O(n2)O(n2)O(n2)(1.1.1.1)(1.1.1.2)(1.1.1.3)(1.1.1.4)(1.1.1.5)

1.1.2 符号 Ω

  Ω,读作“omega”, Ω(g(n)) 是增长次数大于等于 g(n) 及其常数倍( n 趋向于无穷大)的函数集合。
  定义 如果函数f(n)包含在 Ω(g(n)) 中,记作 f(n)=Ω(n)) 。它的成立条件是:对于所有足够大的 n f(n)的下界由 g(n) 的常数倍所确定,也就是说,存在大于0的常数 c 和非负整数n0,使得:

对于所有的 nn0 来说, f(n)c(g(n)

  下图说明了这个定义:

  下面给出几个例子:

n312n(n1)100n+5=Ω(n2)=Ω(n2)Ω(n2)(1.1.2.1)(1.1.2.2)(1.1.2.3)

1.1.3 符号 Θ

  读作“theta”。
  定义 如果函数f(n)包含在 Θ(g(n)) 中,记作 f(n)=Θ(n)) 。它的成立条件是:对于所有足够大的 n f(n)的上界和下界由 g(n) 的常数倍所确定,也就是说,存在大于0的常数 c1,c2 和非负整数 n0 ,使得:

对于所有的 nn0 来说, c1g(n)f(n)c2g(n)

  下图说明了这个定义:

  下面给出几个例子:

12n(n1)6n3=Θ(n2)Θ(n2)(c1=14,c2=12,n0=2)(1.1.3.2)

1.2 符号的性质

  定理 如果 t1(n)=O(g1(n)) 并且 t2(n)=O(g2(n)) ,则

t1(n)+t2(n)=O(max{g1(n),g2(n)})

对于 Ω Θ符号,同样成立。
  证明 增长次数的证明是基于以下简单事实:对于 4 个任意实数a1,b1,a2,b2,如果 a1b1 并且 a2b2 ,则 a1+a22max{b1,b2}
  因为 t1(n)=O(g1(n)) ,存在正常量 c1 和非负整数 n1 ,使得:

对于所有的 nn1,t1(n)c1g1(n)

  同样,因为 t2(n)=O(g2(n))

对于所有的 nn2,t2(n)c2g2(n)

  假设 c3=max{c1,c2} 并且 nmax{n1,n2} ,就可以利用两个不等式的结论将其相加,得出以下结论:

t1(n)+t2(n)c1g1(n)+c2g2(n)c3g1(n)+c3g2(n)=c3[g1(n)+g2(n)]c32max{g1(n),g2(n)}(1.2.1)(1.2.2)(1.2.3)

  那么,对于两个连续执行部分组成的算法,应该如何应用这个特性呢?它意味着该算法的整体效率是由具有较大增长次数的部分所决定的,即效率较差的部分决定

二:复杂度求解方法分析

  对于一个普通函数(即非递归函数),其时间复杂度自然易求。下面我们主要谈谈如何求解递归函数的时间复杂度。
  递归函数通常会有以下的方程式:

T(n)=aT(nb)+f(n)(2.1)

其中, a1,b>1 ,且都是常数, f(n) 是渐近正函数。递归式(2.1)描述的是这样一种算法的运行时间:它将规模为 n 的问题分解为a个子问题,每个子问题规模为 nb ,其中 a1,b>1 a 个子问题递归地求解,每个花费时间T(nb)。函数 f(n) 包含了问题分解和子问题解合并的代价。
  常用的方法有两种:主定理分治法

2.1 主定理(Master Theorem)

  定理 a1,b>1 ,且都是常数, f(n) 是一个函数, T(n) 是定义在非负整数上的递归式,即:

T(n)=aT(nb)+f(n)

其中我们将 nb 解释为 nb nb 。那么 T(n) 有如下渐近界:
  (Case 1)如果 f(n)=O(nc) ,其中 c<logba ,则:

T(n)=Θ(nlogba)

  (Case 2)如果存在常数 k0 ,使 f(n)=Θ(nclogkn) ,其中 c=logba ,则:

T(n)=Θ(nclogk+1n)

  (Case 3)如果 f(n)=Ω(nc) ,其中 c>logba ,并且对某个常数 k<1 和所有足够大的 n af(nb)kf(n),则:

T(n)=Θ(f(n))

  算法导论已有关于这个定理的证明,故此处省略,有兴趣的读者可以去翻阅下。

2.2 分治法

  分治法先把给定的实例划分为若干个较小的实例,对每个实例递归求解,然后如果有必要,再把较小实例的解合并成给定实例的一个解。假设所有较小实例的规模都为 nb ,其中 a 个实例需要实际求解,对于n=bk,k=1,2,3...,其中 a1,b>1 ,得到以下结果:

T(n)T(bk)=aT(nb)+f(n)=aT(bk1)+f(bk)=a[aT(bk2)+f(bk1)]+f(bk)=a2T(bk2)+af(bk1)+f(bk)=a3T(bk3)+a2f(bk2)+af(bk1)+f(bk)=...=akT(1)+ak1f(b1)+ak2f(b2)+...+a0f(bk)=ak[T(1)+j=1kf(bj)aj]()(2.2.2)(2.2.3)(2.2.4)(2.2.5)(2.2.6)(2.2.7)

  由于 ak=alogbn=nlogba ,当 n=bk 时,对于式(2.2.7)我们可以推出下式:

T(n)=nlogba[T(1)+j=1logbnf(bj)aj](2.2.8)

  显然, T(n) 的增长次数取决于常数 a b的值以及函数 f(n) 的增长次数。

三:无意发现的定理

  以下是我自己在演算时无意发现的,并给出了证明。
  该定理依旧建立在递归方程式中,即:

T(n)=aT(nb)+f(n)(a1,b>1)

根据以上的方程式有以下两个定理:

定理1

  定理1 对于递归方程式,若 a=1,b>1,f(n)=c,c 为某个常数,即:

T(n)=T(nb)+c

  则:

T(n)=Θ(logn)

  证明 应用主定理 Case 2,其中 c=logba=logb1=0 ,再使 k=0 ,则 f(n)=Θ(nclogkn)=Θ(1) ,这里的 f(n) 即等于常数 c ,证明成立。

定理2

  定理2 对于递归方程式,若a=1,b>1,f(n)=kn+p,其中 k>0,p>0 且为某个常数(也就是 f(n) 是一个线性直线方程),即:

T(n)=T(nb)+(kn+p)(b>1,k>0,p)

  则:

T(n)=Θ(n)

  证明 应用分治法中式(2.2.8):

T(n)=nlogba[T(1)+j=1logbnf(bj)aj]=j=1logbn(kbj+p)=plogbn+kbb1(n1)<pn+kbb1(n1)=cnkbb1=Θ(n)(3.2.1)(3.2.2)(k>0,p>0,b>1)(3.2.4)(c>0)(3.2.5)

证明成立。

四:总结

  第一部分辨析了 O,Ω,Θ 三种符号的区别以及它们的性质。
  第二部分介绍了两种常用的计算时间复杂度方法,即主定理和分治法。
  第三部分给出了个人在演算时发现的两个定理,并给出了证明,题外话,这两条定理比较实用,希望读者能够熟记。另外如果您在其它网站看到类似原创定理,纯属巧合,勿喷。

参考文献:
[1] Thomas H.Cormen,etc. 算法导论(第三版).
[2] Anany Levitin. 算法设计与分析基础(第三版).
[3] . Master theorem. Wikipedia.

文章转自我的个人博客:http://www.61mon.com/index.php/archives/176/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值