关于主定理的一个简洁的证明
upd on 2025.5.10 修改了一处笔误。
前言
上个赛季某次在 1121 训练时吐槽主定理难证,被翔哥听到骂了一顿,然后他给我讲了一种跟网上主流的证明方法非常不同的方法,仅用到高中学的简单的数列递推和归纳法,令我耳目一新,不过当时一带而过了,并没有记录下来。
直到今天的算法设计与分析课上重新提到了主定理,我再次从网上搜索证明,还是只能搜到那些长篇大论的推导,于是我重新回忆了一下翔哥教给我的推导方法,并打算开个博客记录一下。
定理
主定理适用于求解如下递归式算法的时间复杂度
T(n)=aT(bn)+O(nd)
结论为
T(n)=⎩⎨⎧O(nd) O(ndlogn)O(nlogba)(bd>a)(bd=a)(bd<a)
证明
令
n=bk(如果无法取整,则可以找到最小的
k 使得
bk>n,根据后续结论,这样做对时间复杂度只会产生常数级别的影响),则递归式可写为
T(bk)=aT(bk−1)+O(bkd)
-
先来分析
bd=a 时的情况,此时递归式可写为
T(bk)=aT(bk−1)+O(ak)
akT(bk)=ak−1T(bk−1)+O(1)
不难发现
akT(bk)=O(k)
即
T(n)=T(bk)=O(akk)=O(bkdk)=O(ndlogn)
-
当
bd>a 时,考虑归纳法。
显然,当
k=0 时,
T(bk)=T(1)=O(1)=O(bkd) 成立。
假设
T(bk)=O(bkd) 在
k≤K 时成立。
考虑在
k=K+1 时,带入递归式得
T(bK+1)=aT(bK)+O(b(K+1)d)=O(abKd+b(K+1)d)
由于
bd>a,所以
abKd<bdbKd=b(K+1)d,故
T(bK+1)=aT(bK)+O(b(K+1)d)=O(b(K+1)d)
即
T(bk)=O(bkd) 在
k=K+1 时也成立,故
T(n)=T(bk)=O(bkd)=O(nd)
-
当
bd<a 时,同理,也考虑归纳法。
显然,当
k=0 时,
T(bk)=T(1)=O(1)=O(ak) 成立。
假设
T(bk)=O(ak) 在
k≤K 时成立。
考虑在
k=K+1 时,带入递归式得
T(bK+1)=aT(bK)+O(b(K+1)d)=O(aK+1+b(K+1)d)
由于
bd<a,所以
aK+1>(bd)K+1=b(K+1)d,故
T(bK+1)=aT(bK)+O(b(K+1)d)=O(aK+1)
即
T(bk)=O(ak) 在
k=K+1 时也成立,故
T(n)=T(ak)=O(bk(logba))=O(nlogba)