算法导论(二)--渐近符号 递归 和解法

算法导论(二)--渐近符号 递归 和解法

基本渐近符号

O符号

首先看一个式子: f ( n ) = O ( g ( n ) ) f(n)=O(g(n)) f(n)=O(g(n))表示存在适当的常数c>0,和n0>0使得 0 ≤ f ( n ) ≤ c ⋅ g ( n ) 0\leq f(n)\leq c·g(n) 0f(n)cg(n),对于充分大的n>n0成立。其实就是f(n)以g(n)为上界。举个例子:2n2=O(n3),表示去掉左边的首项系数和低阶项,剩下的小于等于n3。这个等式并不对称,因为我们不能说n3=O(2n2)。
其实本质的想法就是f(n)属于g(n)构成的函数集。即定义O(g(n))为一个函数集,集合内的函数称为f(n),上面的等号其实表示属于的意思。这是另一种定义方式: O ( g ( n ) ) = { f ( n ) : O(g(n))=\{f(n): O(g(n))={f(n):存在常数c>0,n0>0,使得对所有的n>n0,有 0 ≤ f ( n ) ≤ c ⋅ g ( n ) } 0\leq f(n)\leq c·g(n)\} 0f(n)cg(n)}
再举个例子,f(n)=n3+O(n2)表示了一个误差界限,f(n)主要是n3,但是还有一些低阶项O(n2)。具体来说,即存在某函数h(n)在函数集O(n2)中,使得f(n)=n3+h(n),总的来说,有低阶项,以某个常数乘以n2为上界,对足够大的n成立。
再举个例子,n2+O(n)=O(n2),表示对任意的f(n)属于O(n),都有h(n)属于O(n2),使得n2+f(n)=h(n)。但是反之不成立。

Ω符号

O符号表示了运行时间的上界,但有时我们还需要下界,也就是Ω符号。和之前的相似, Ω ( g ( n ) ) = { f ( n ) : Ω(g(n))=\{f(n): Ω(g(n))={f(n):存在常数c>0,n0>0,使得对所有的n>n0,有 0 ≤ c ⋅ g ( n ) ≤ f ( n ) } 0\leq c·g(n)\leq f(n)\} 0cg(n)f(n)}。举个例子, n = Ω ( l o g n ) \sqrt{n}=Ω(logn) n =Ω(logn)表示对于充分大的n, n \sqrt{n} n 至少是logn的常数倍。

Θ符号

Θ ( g ( n ) ) = { f ( n ) : Θ(g(n))=\{f(n): Θ(g(n))={f(n):存在常数c1>0, c2>0, n0>0,使得对所有的n>n0,有 0 ≤ c 1 ⋅ g ( n ) ≤ f ( n ) ≤ c 2 ⋅ g ( n ) } 0\leq c_1·g(n)\leq f(n)\leq c_2·g(n)\} 0c1g(n)f(n)c2g(n)}。举个例子,n2/2=Θ(n2)。

解递归式

解递归式就是找出递归式的解的渐近Θ或O界的方法。这就像解微分方程,没有一个通用的方法,而是有一堆方法,然后检验。下面是几种主流方法。

代换法

代换法可以用来确定一个递归式的上界或下界,主要思想是猜答案。我们不需要完全猜出来,不需要知道常数系数确切是多少,只需要猜它的形式,然后按照数学归纳法检验。

举例:求 T ( n ) = 4 T ( n / 2 ) + n T(n)=4T(n/2)+n T(n)=4T(n/2)+n 的上界

  • 猜想T(n)=O(n3)
    代换法中不能用O符号,因为如果有一条有穷的O关系序列,n2是O(n3)的,是O(n4)的,这样开始和最后就不一致了。比如你想证明n=O(1) ,这显然是错的。首先1=O(1),然后归纳,假设n-1=O(1),那就可以推出n=O(1)+1=O(1)。这是错误的证明,不能再O符号上进行归纳,因为这里的常数其实是依赖于n变化的。
    因此用常数展开,假设T(k)≤ck3,k<n。首先T(1)=Θ(1)≤c,然后计算T(n)。
    T(n)=4T(n/2)+n
    ≤4·c (n/2)3+n
    =1/2·c·n3+n
    =cn3-(1/2cn3-n)
    ≤cn3,c≥1,n≥1
    这是一个上界,但还不够严格,不能说明答案就是O(n3),只能说最多是O(n3)
  • 猜想T(n)=O(n2)
    假设T(k)≤ck2,k<n
    T(n)=4T(n/2)+n
    ≤4·c (n/2)2+n
    =c·n2+n
    >cn2,这个假设不成立
  • 猜想T(k)≤c1k2-c2k,k<n
    T(n)=4T(n/2)+n
    ≤4[c1(n/2)2-c2(n/2)]+n
    =c1n2-(1-2c2)n
    =c1n2-c2n-(c2-1)n
    ≤c1n2-c2n,c2>1,c1>c2
    得到了正确答案。

递归树法

代换法有时候很难想到一个好的猜测,这种时候递归树是一个很好的方法。
例子1:
T ( n ) = 3 T ( n / 4 ) + c n 2 T(n)=3T(n/4)+cn^2 T(n)=3T(n/4)+cn2 的上界
在这里插入图片描述
上图显示了这个递归树的演化过程,这种写法很奇怪,但很有用。b)中根部的cn2表示递归在顶层时花的代价,下面子树表示子问题的代价,这棵树就是对a)中的T(n)的展开。子树又可以向下扩展,c)中T(n/4)又可以拆成c(n/4)2和三个T(n/16),扩展直到递归结束。子问题里根节点越来越远,大小也越来越小,最后一定会到达一个边界条件。
那么这棵树的深度是多少呢?对深度为i的节点,子问题的大小是n/4i,递归结束时n/4i=1,i=log4n,所以这棵树有log4n+1层,即层0,1,…,log4n。然后计算每一层的代价,深度为i时的节点数是3i,每个节点的代价是c·(n/4i)2,因此第i层的总代价就是c·(n/4i)2·3i=(3/16)i·c·n2,i=0,1,…,log4n-1。最后一层,也就是深度为log4n的每个节点代价都是O(1),代价为T(1)·3log4n=T(1)·nlog43。所以总代价就是:
在这里插入图片描述
放缩得到:
在这里插入图片描述
然后用代换法可以证明正确性。

例子2:
T ( n ) = T ( n / 3 ) + T ( 2 n / 3 ) + O ( n ) T(n)=T(n/3)+T(2n/3)+O(n) T(n)=T(n/3)+T(2n/3)+O(n)
跟前面一样,还是用c表示O(n)的常数因子,即 T(n)=T(n/3)+T(2n/3)+cn。递归树如下图所示:
在这里插入图片描述
可以发现每一层的代价和都是cn。向下扩展不是等深度的,不是所有层都是cn,但我们只需要猜一个大概然后用代换法验证。从根节点到叶节点的最长路径是n->2n/3->4n/9->…->(2/3)in->…->1,(2/3)in=1,i=log3/2n,所以深度是log3/2n。因此T(n)=O(cn·log3/2n)=O(nlogn)。

主方法

主方法只对一些特定形式的递归式有用,相当于是个公式。形如 T(n)=aT(n/b)+f(n)才能用主方法,这个式子中,每个子问题有相等的规模,有一些约束条件,a≥1,至少递归一次,b>1,子问题规模得不断减小,f(n)要渐近趋正(表示对足够大的n,f(n)是正的)。
主方法的思路就是去比较非递归的函数f(n)和函数nlogba。这个nlogba有没有很熟悉,它就是递归树中叶节点的数量。

主定理

  1. 如果f(n)=O(nlogba-ε),ε>0,那么T(n)=Θ(nlogba)
  2. 如果f(n)=Θ(nlogba·lgkn),k≥0,表示f(n)=基本等于Θ(nlogba),那么T(n)=Θ(nlogba·lgk+1n)
  3. 如果f(n)比nlogba增长得快,即f(n)=Ω(nlogba+ε),ε>0,并且递归中f(n)要不断减小,即af(n/b)≤(1-ε’)·f(n),ε’>0,那么T(n)=Θ(f(n))

举例:

  1. T ( n ) = 4 T ( n / 2 ) + n T(n)=4T(n/2)+n T(n)=4T(n/2)+n
    这里a=4,b=2,f(n)=n,nlogba=nlog24=n2,因此满足定理中1的情况,T(n)=Θ(n2)
  2. T ( n ) = 4 T ( n / 2 ) + n 2 T(n)=4T(n/2)+n^2 T(n)=4T(n/2)+n2
    这里a=4,b=2,f(n)=n2,nlogba=n2,满足定理中的2,k=0,T(n)=Θ(n2·lgn)
  3. T ( n ) = 4 T ( n / 2 ) + n 3 T(n)=4T(n/2)+n^3 T(n)=4T(n/2)+n3
    这里a=4,b=2,f(n)=n3,nlogba=n2,满足定理中的3,T(n)=Θ(n3)
  4. T ( n ) = 4 T ( n / 2 ) + n 2 / l g n T(n)=4T(n/2)+n^2/lgn T(n)=4T(n/2)+n2/lgn
    这里f(n)=n2/lgn,主定理不适用,得找别的方法

主定理为什么是正确的?
对于 T ( n ) = a T ( n / b ) + f ( n ) T(n)=aT(n/b)+f(n) T(n)=aT(n/b)+f(n) 画出来的递归树,如下图所示:
在这里插入图片描述
这棵树的高度是logbn+1,每一层的节点个数是ai,叶节点的个数就是alogbn,也就是nlogba,每个叶节点复杂度都是Θ(1),将底层的代价加起来得到Θ(nlogba)。
现在我们比较树顶层的复杂度f(n)和底层的复杂度Θ(nlogba),如果下面的子树以几何级数递减,那么f(n)就会占主导地位,因此在主定理的3中,就得到Θ(f(n))。
在主定理的1中,f(n)多项式地小于Θ(nlogba),可以说是从中间改变了顺序,子树以几何级数增长,因此叶节点占主导地位,即Θ(nlogba)。
在主定理的2中,顶层与底层基本相等,因此代价是其中的某一层的复杂度乘以树的高度,即Θ(f(n)·lgn)=Θ(nlogba·lgkn·logbn)=Θ(nlogba·lgn)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值