zoukankan      html  css  js  c++  java
  • 重谈主定理(master定理)及其证明

    参考文章:

    【洛谷日报#33】时空复杂度分析及master定理

    李卿. 递归算法分析中主定理的应用[J]. 黑龙江科技信息, 2011(29):97+207.

    Thomas H.Cormen,Charles E.Leiserson,Ronald L.Rivest,Clifford Stein. 殷建平等译. 算法导论第三版 [M]. 北京:机械工业出版社,2013,55-58.

    前言:

    本篇文章与我的 博客园 同步更新。

    在此之前,请先阅读 【洛谷日报#33】时空复杂度分析及master定理,其中关于时间复杂度表示的基础知识不再阐述。

    引出:

    现在考虑一个问题:假设某算法的计算时间表示为递归式:

    [egin{aligned}T(n)&=2T(frac{n}{2})+nlog n\T(1)&=1end{aligned} ]

    求该算法的时间复杂度。

    当给你抛出这么一个题型时,你怎么办?

    凭经验和感觉蒙

    小几率能蒙对,但你觉得这种题CCF会送你分吗?

    递归进去

    像这样递归进去:

    [egin{aligned}T(n)&=2T(frac{n}{2})+nlog n\&=2left(2T(frac{n}{4})+frac{n}{2}log(frac{n}{2}) ight)+nlog n\&=2left(2left(2T(frac{n}{8})+frac{n}{4}log(frac{n}{4}) ight)+frac{n}{2}log(frac{n}{2}) ight)+nlog n\&cdotsend{aligned} ]

    每项都 (ndiv 2),总共递归 (log_2 n) 层:

    [T(n)=Oleft(log ncdot(nlog n+nlog(frac{n}{2})+nlog(frac{n}{2^2})+cdots+nlog(frac{n}{2^{log_2 n}})) ight) ]

    (T(n)=O(nlog^2 n))

    这么做不是没有道理,但是如果 (T(n)=3T(frac{n}{4})+nlog n),用这种方法根本算不出来(或许可以算出来,但是操作极其麻烦)。

    主定理(master定理)求解

    主定理:(a,b) 是常数,(f(n)) 为额外附加值函数(T(n)) 为递归式 (T(n)=aT(frac{n}{b})+f(n)quad(a>0,b>1)),就有:

    1. (f(n)=O(n^{(log_ba)-epsilon})) 其中 (epsilon>0) 是一个常数(相当于 (log_ba>f(n))),则有 (T(n)=Theta(n^{log_ba}))
    2. (f(n)=Theta(n^{log_ba})),则有 (T(n)=Theta(n^{log_ba}log n))
    3. (f(n)=Omega(n^{(log_ba)+epsilon})) 其中 (epsilon>0) 是一个常数(相当于 (log_ba<f(n))),且对于一个常数 (c<1) 和所有足够大的 (n)(af(frac{n}{b})leq cf(n))(这一条在这里可以暂时忽略不看,但在证明时起到至关重要的作用),则有 (T(n)=Theta(f(n))).
    4. (f(n)=Theta(n^{log_ba}log^kn)) 其中 (kgeq1) 是一个常数,则有 (T(n)=Theta(n^{log_ba}log^{k+1}n))

    这么看着有点枯燥乏味的样子,不利于理解,但如果丢掉定理四的话(毕竟CSP/NOIp好像真的没考过定理四,其实可以发现定理二和定理四其实是同一种,便于萌新理解就分开了),主定理的定义可以直接写成:

    图一

    (图一)

    也就是 (n^{log_ba})(f(n)) 进行比较!

    图一、算法导论和上面提过的论文没有提到过定理四,但是原来那篇日报(#33)有,对此我想说,洛谷日报真是太好了!导论不行!日报行!(老伏拉夫了

    举例说明:

    例一:(T(n)=4T(frac{n}{2})+n),此时 (a=4,b=2,epsilon=1),那么 (log_ba=log_24=2,f(n)=O(n^{log_ba-epsilon})=O(n^{2-1}))(f(n)) 成立,所以 (T(n)=Theta(n^{log_ba})=Theta(n^2))

    例二:(T(n)=2T(frac{n}{2})+n),此时 (a=2,b=2),那么 (log_ba=log_22=1,f(n)=Theta(n^{log_ba})=Theta(n))(f(n)) 成立,所以 (T(n)=Theta(n^{log_ba})=Theta(n))

    例三:(T(n)=4T(frac{n}{2})+n^3),此时 (a=4,b=2,epsilon=1),那么 (log_ba=log_24=2,f(n)=Omega(n^{log_ba+epsilon})=Omega(n^{2+1})),对于 (c=frac{2}{3}) 和够大的 (n)(left(af(frac{n}{b})=4(frac{n}{2})^3=4(frac{n^3}{8})=frac{n^3}{2} ight)leq left(cf(n)=frac{2n^3}{3} ight))(f(n)) 成立,所以 (T(n)=Theta(f(n))=Theta(n^3))

    例二:(T(n)=2T(frac{n}{2})+nlog n),此时 (a=2,b=2,k=1),那么 (log_ba=log_22=1,f(n)=Theta(n^{log_ba}+log^kn)=Theta(nlog n))(f(n)) 成立,所以 (T(n)=Theta(n^{log_ba}log^{k+1}n)=Theta(nlog^2 n))

    证明:

    先声明:证明又长又臭,有亿点点难理解,学有余力的 dalao 可以来康康。

    俗话说得好:“欲要证明master,就先画棵递归树”:

    图二

    (图二)

    关于图二的解释及证明:

    对于第 (i) 层((i e log_bn)),有 (a^i) 个节点,而每个节点的值是 (f(frac{n}{b^i})),那么第 (i) 层总共的值是 (a_if(frac{n}{b^i}))

    对于第 (log_bn) 层,有 (a^{log_bn}) 个节点,而每个节点的时间复杂度是 (Theta(1)),那么这一层总共的时间复杂度是 (Theta(a^{log_bn})=Theta(n^{log_ba})) 层。

    对于 (a^{log_bn}=n^{log_ba}) 的证明:

    [egin{aligned}a^{log_bn}&=b^{{log_ba}^{log_bn}}\&=b^{{log_bn}^{log_ba}}\&=n^{log_ba}end{aligned} ]

    (a^{log_bn}=n^{log_ba}) 得证。

    这么看,图二的递归树的总时间复杂度为 (T(n)=Theta(n^{log_ba})+sum_{j=0}^{log_bn-1}a^jf(frac{n}{b^j})),就是叶子节点层加上其它结点层的值。

    证明*:

    根据上文这个 (T(n)) 的时间复杂度,我们定义一个函数 (g(n))

    [g(n)=sum_{j=0}^{log_bn-1}a^jf(frac{n}{b^j}) ]

    这个 (g(n)) 有一些性质:

    1. (f(n)=O(n^{(log_ba)-epsilon})) 其中 (epsilon>0) 是一个常数,则有 (g(n)=O(n^{log_ba}))
    2. (f(n)=Theta(n^{log_ba})) 时,则有 (g(n)=Theta(n^{log_ba}log n))
    3. (f(n)=Omega(n^{(log_ba)+epsilon})) 其中 (epsilon>0) 是一个常数,且对于一个常数 (c<1) 和所有足够大的 (n)(af(frac{n}{b})leq cf(n)),则有 (g(n)=Theta(f(n))).
    4. (f(n)=Theta(n^{log_ba}log^kn)) 其中 (kgeq1) 是一个常数,则有 (g(n)=Theta(n^{log_ba}log^{k+1}n))

    欸!有没有发现好像在哪见过!那是因为这是我从上文复制下来的(

    证明关于g函数性质*:

    性质 1:

    (f(n)=O(n^{(log_ba)-epsilon})) 代入进 (g(n)=sum_{j=0}^{log_bn-1}a^jf(frac{n}{b^j}))

    [egin{aligned}g(n)&=Oleft(sum_{j=0}^{log_bn-1}a^j(frac{n}{b^j})^{(log_ba)-epsilon} ight)\&=Oleft(sum_{j=0}^{log_bn-1}a^j(frac{n^{(log_ba)-epsilon}}{b^{j^{(log_ba)-epsilon}}}) ight)\&=Oleft(sum_{j=0}^{log_bn-1}n^{(log_ba)-epsilon}(frac{a^j}{b^{j^{(log_ba)-epsilon}}}) ight)\&=Oleft(n^{(log_ba)-epsilon}sum_{j=0}^{log_bn-1}(frac{a}{b^{(log_ba)-epsilon}})^j ight)\&=Oleft(n^{(log_ba)-epsilon}sum_{j=0}^{log_bn-1}(frac{ab^epsilon}{a})^j ight)\&=Oleft(n^{(log_ba)-epsilon}sum_{j=0}^{log_bn-1}(b^epsilon)^j ight)end{aligned} ]

    然后根据等比数列求和公式化简 (sum_{j=0}^{log_bn-1}(b^epsilon)^j)

    [egin{aligned}g(n)&=Oleft(n^{(log_ba)-epsilon}(frac{b^{epsilonlog_bn}-1}{b^{epsilon}-1}) ight)\&=Oleft(n^{(log_ba)-epsilon}(frac{n^{epsilon}-1}{b^{epsilon}-1}) ight)end{aligned} ]

    这里回想一下 (b,epsilon) 的定义,(做到不忘初心牢记使命),它们是常数,所以式子中 (frac{1}{b^{epsilon}-1}) 也是常数,应忽略:

    [egin{aligned}g(n)&=Oleft(n^{(log_ba)-epsilon}cdot n^{epsilon} ight)\&=O(n^{log_ba})end{aligned} ]

    性质 1 得证。

    性质 2:

    性质 1 和性质 2 操作一样,就是一直代入再一直化简,将 (f(n)=Theta(n^{log_ba})) 代入进 (g(n)=sum_{j=0}^{log_bn-1}a^jf(frac{n}{b^j}))

    [egin{aligned}g(n)&=Thetaleft(sum_{j=0}^{log_bn-1}a^jleft(frac{n}{b^j} ight)^{log_ba} ight)\&=Thetaleft(sum_{j=0}^{log_bn-1}a^jleft(frac{n^{log_ba}}{b^{j^{log_ba}}} ight) ight)\&=Thetaleft(n^{log_ba}sum_{j=0}^{log_bn-1}left(frac{a^j}{b^{j^{log_ba}}} ight) ight)\&=Thetaleft(n^{log_ba}sum_{j=0}^{log_bn-1}left(frac{a}{b^{log_ba}} ight)^j ight)\&=Thetaleft(n^{log_ba}sum_{j=0}^{log_bn-1}1 ight)\&=Thetaleft(n^{log_ba}log_bn ight)end{aligned} ]

    注意:这里重头戏来了!式子中的 (log_bn) 是可以直接改底数的,因为可以通过换底公式得到对数函数都是同级的。因此我们可以把 (b) 改成 (2)(即 (log_bn) 化成 (log n)):

    [g(n)=Thetaleft(n^{log_ba}log n ight) ]

    性质 2 得证。

    性质 3:

    性质 3 是最特殊的,用 (af(frac{n}{b})leq cf(n)) 递归 (j) 次可以得到 (a^j f(frac{n}{b^j})leq c^j f(n))。再用这个式子套 (g(n)) 定义:

    [egin{aligned}g(n)leqsum_{j=0}^{log_bn-1}c^jf(n)&Rightarrow g(n)leq f(n)sum_{j=0}^{log_bn-1}c^j\&Rightarrow g(n)leq f(n)sum_{j=0}^{infty}c^jend{aligned} ]

    解释一下上面的式子,因为 (c) 都是正数,所以如果 (g(n)leq f(n)sum_{j=0}^{log_bn-1}c^j),显然 (g(n)leq f(n)sum_{j=0}^{infty}c^j)。而这么做是为了更好证明。

    接下来还是用等比数列求和公式化简:

    [egin{aligned}g(n)leq f(n)sum_{j=0}^{infty}c^jRightarrow g(n)leqleft(frac{1}{1-c} ight)f(n)end{aligned} ]

    你可能好奇这个等比数列求和是怎么化的,下面证明一下:

    (S=c^0+c^1+c^2+cdots+c^{infty}) 表示 (sum_{j=0}^{infty}c^j),此时公比为 (c)

    (cS=c^1+c^2+c^3+cdots+c^{infty}),这里 (infty+1=infty)

    ((1-c)S=c^0=1)

    (S=frac{1}{1-c})

    (sum_{j=0}^{infty}c^j=frac{1}{1-c})

    回到题目,由 (g(n)leqleft(frac{1}{1-c} ight)f(n)) 得到 (g(n)=O(f(n)))

    而根据 (g(n)) 的定义 (g(n)=f(n)+af(frac{n}{b})+a^2f(frac{n}{b^2})+cdots+a^{log_bn-1}f(frac{n}{b^{log_bn-1}})geq f(n)),得到 (g(n)=Omega(f(n)))

    所以 (g(n)=Theta(f(n)))

    性质 3 得证。

    性质 4:

    老套路,将 (f(n)=Theta(n^{log_ba}log^kn)) 代入进 (g(n)=sum_{j=0}^{log_bn-1}a^jf(frac{n}{b^j}))

    [egin{aligned}g(n)&=Thetaleft(sum_{j=0}^{log_bn-1}a^jleft(frac{n}{b^j} ight)^{log_ba}log^kleft(frac{n}{b^j} ight) ight)\&=Thetaleft(sum_{j=0}^{log_bn-1}a^jleft(frac{n^{log_ba}}{b^{j^{log_ba}}} ight)left(log n-log b^j ight)^k ight)\&=Thetaleft(n^{log_ba}sum_{j=0}^{log_bn-1}left(frac{a^j}{b^{j^{log_ba}}} ight)left(log^k n-log^k b^j ight) ight)\&=Thetaleft(n^{log_ba}sum_{j=0}^{log_bn-1}left(frac{a}{b^{log_ba}} ight)^jleft(log^k n-log^k b^j ight) ight)\&=Thetaleft(n^{log_ba}sum_{j=0}^{log_bn-1}log^k n-log^k b^j ight)\&=Thetaleft(n^{log_ba}left(log_bncdotlog^k n-sum_{j=0}^{log_bn-1}log^k b^j ight) ight)\&=Thetaleft(log_bncdotlog^k ncdot n^{log_ba}-n^{log_ba}sum_{j=0}^{log_bn-1}log^k b^j ight)end{aligned} ]

    和性质 2 一样: (log_bn) 可以直接化为 (log n)。然后 (-n^{log_ba}sum_{j=0}^{log_bn-1}log^k b^j) 是一个负数,在时间复杂度的表示中可以忽略,所以得到:

    [egin{aligned}g(n)&=Thetaleft(n^{log_ba}log^{k+1}n ight)end{aligned} ]

    性质 4 得证。

    主定理总时间复杂度证明:

    回到图二的总时间复杂度 (T(n)=Theta(n^{log_ba})+sum_{j=0}^{log_bn-1}a^jf(frac{n}{b^j}))

    (f(n)=O(n^{(log_ba)-epsilon})) 时:

    [egin{aligned}T(n)&=Theta(n^{log_ba})+sum_{j=0}^{log_bn-1}a^jf(frac{n}{b^j})\&=Theta(n^{log_ba})+g(n)\&=Theta(n^{log_ba})+O(n^{log_ba})\&=Theta(n^{log_ba})end{aligned} ]

    (f(n)=Theta(n^{log_ba})) 时:

    [egin{aligned}T(n)&=Theta(n^{log_ba})+sum_{j=0}^{log_bn-1}a^jf(frac{n}{b^j})\&=Theta(n^{log_ba})+g(n)\&=Theta(n^{log_ba})+Theta(n^{log_ba}log n)\&=Theta(n^{log_ba}log n)end{aligned} ]

    (f(n)=Omega(n^{(log_ba)+epsilon})),且对于一个常数 (c<1) 和所有足够大的 (n)(af(frac{n}{b})leq cf(n))

    [egin{aligned}T(n)&=Theta(n^{log_ba})+sum_{j=0}^{log_bn-1}a^jf(frac{n}{b^j})\&=Theta(n^{log_ba})+g(n)\&=Theta(n^{log_ba})+Theta(f(n))\&=Theta(f(n))end{aligned} ]

    (f(n)=Theta(n^{log_ba}log^kn)) 时:

    [egin{aligned}T(n)&=Theta(n^{log_ba})+sum_{j=0}^{log_bn-1}a^jf(frac{n}{b^j})\&=Theta(n^{log_ba})+g(n)\&=Theta(n^{log_ba})+Theta(n^{log_ba}log^{k+1}n)\&=Theta(n^{log_ba}log^{k+1} n)end{aligned} ]

    主定理证毕。

    后记 & 感谢名单:

    在这篇文章证明的主定理只是对于 (b) 的幂下的,就是说向上、向下取整的没有证明,但要证明这些实在太难了,要花费更长的时间 (主要还是懒

    我在查找资料的时候发现还有一种定理——Akra-Bazzi定理(打开要梯子)也是时间复杂度的。

    感谢名单(排名不分先后):

    @stoorz

    @bruteforce_

    @SSL_TJH_蒟蒻

    @RABU

  • 相关阅读:
    PHP无法使用file_get_contents或者curl_init()函数解决办法
    EXT 删除 监听
    PHP调试工具Xdebug安装配置教程
    Linux常用命令大全
    js中setInterval与setTimeout用法
    基于Web过程模拟的动态Web信息获取
    HNU2[J题]Modified LCS 扩展GCD
    SQL Server 2005定时备份维护操作步骤定时备份维护操作步骤定时备份维护操作步骤定时备份维护操作步骤
    object_id (N'...')是什么意思?
    使用TSQL来创建作业(这个比较好)
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/13719879.html
Copyright © 2011-2022 走看看