分治策略递归式时间复杂度的求解方法主要有三种:代入法、递归树和主方法。其中主方法为求解递归式 T ( n ) = a T ( n / b ) + f ( n ) T(n)=aT(n/b)+f(n) T(n)=aT(n/b)+f(n)提供了一种“菜谱”式的求解方法。
公式: T ( n ) = a T ( n / b ) + f ( n ) T(n)=aT(n/b)+f(n) T(n)=aT(n/b)+f(n)
其中
a
≥
1
a\ge1
a≥1和
b
>
1
b>1
b>1是常数,
f
(
n
)
f(n)
f(n)是渐近正函数。
递归式描述了这样一种算法的运行时间:它将规模为
n
n
n的问题分解成
a
a
a个子问题,每个子问题的规模是
n
/
b
n/b
n/b,其中
a
a
a和
b
b
b都是正常数。
a
a
a个子问题递归地进行求解,每个花费时间
T
(
n
/
b
)
T(n/b)
T(n/b)。函数
f
(
n
)
f(n)
f(n)包含了问题分解和子问题解合并的代价。
从技术的正确性方面看,此递归式并不是良好定义的,因为
n
/
b
n/b
n/b可能不是整数。但将
T
(
n
/
b
)
T(n/b)
T(n/b)替换成
T
(
⌊
n
/
b
⌋
)
T(\lfloor{n/b}\rfloor)
T(⌊n/b⌋)或者
T
(
⌈
n
/
b
⌉
)
T(\lceil{n/b}\rceil)
T(⌈n/b⌉),并不影响递归的渐近性质。
主定理
主方法依赖于主定理。
定理 令
a
≥
1
a\ge1
a≥1和
b
>
1
b>1
b>1是常数,
f
(
n
)
f(n)
f(n)是一个函数,
T
(
n
)
T(n)
T(n)是定义在非负整数上的递归式:
T
(
n
)
=
a
T
(
n
/
b
)
+
f
(
n
)
T(n)=aT(n/b)+f(n)
T(n)=aT(n/b)+f(n)
其中
n
/
b
n/b
n/b可以看作
⌊
n
/
b
⌋
\lfloor{n/b}\rfloor
⌊n/b⌋或者
⌈
n
/
b
⌉
\lceil{n/b}\rceil
⌈n/b⌉。那么
T
(
n
)
T(n)
T(n)有如下渐近界:
- 若对于某个常数 ε > 0 \varepsilon>0 ε>0 有 f ( n ) = O ( n l o g b a − ε ) f(n)=O(n^{log_b{a-\varepsilon}}) f(n)=O(nlogba−ε),则 T ( n ) = Θ ( n l o g b a ) T(n)=\Theta(n^{log_ba}) T(n)=Θ(nlogba)。
- 若 f ( n ) = Θ ( l o g b a ) f(n)=\Theta(log_ba) f(n)=Θ(logba),则 T ( n ) = Θ ( n l o g b a l g n ) T(n)=\Theta(n^{log_ba}{lgn}) T(n)=Θ(nlogbalgn)。
- 若对于某个常数 ε > 0 \varepsilon>0 ε>0 有 f ( n ) = Ω ( n l o g b a + ε ) f(n)=\Omega(n^{log_b{a+\varepsilon}}) f(n)=Ω(nlogba+ε),且对某个常数 c < 1 c<1 c<1和所有足够大的 n n n有 a f ( n / b ) ≤ c f ( n ) af(n/b)\le{c}f(n) af(n/b)≤cf(n),则 T ( n ) = Θ ( f ( n ) ) T(n)=\Theta(f(n)) T(n)=Θ(f(n))。
对于三种情况的每一种,我们将函数 f ( n ) f(n) f(n)与函数 n l o g b a n^{log_ba} nlogba进行比较。若函数 n l o g b a n^{log_ba} nlogba更大,如情况1,则解为 T ( n ) = Θ ( n l o g b a ) T(n)=\Theta(n^{log_ba}) T(n)=Θ(nlogba)。若函数 f ( n ) f(n) f(n)更大,如情况3,则解为 T ( n ) = Θ ( f ( n ) ) T(n)=\Theta(f(n)) T(n)=Θ(f(n))。若两个函数相等,如情况2,则乘上一个对数因子,解为 T ( n ) = Θ ( n l o g b a l g n ) = Θ ( f ( n ) l g n ) T(n)=\Theta(n^{log_ba}lg{n})=\Theta(f(n)lgn) T(n)=Θ(nlogbalgn)=Θ(f(n)lgn)。
在此直觉之外,我们需要了解一些技术细节。在第一种情况中,不是 f ( n ) f(n) f(n)小于 n l o g b a n^{log_ba} nlogba就够了,而是要多项式意义上的小于。也就是说, f ( n ) f(n) f(n)必须渐近小于 n l o g b a n^{log_ba} nlogba,要相差一个因子 n ε n^\varepsilon nε,其中 ε \varepsilon ε是大于0的常数。在第三种情况中,不是 f ( n ) f(n) f(n)大于 n l o g b a n^{log_ba} nlogba就够了,而是要多项式意义上的大于,而且还要满足“正则”条件 a f ( n / b ) ≤ c f ( n ) af(n/b)\le{cf(n)} af(n/b)≤cf(n)。我们将会遇到的多项式界的函数中,多数都满足此条件。
需要注意的是,这三种情况并未覆盖 f ( n ) f(n) f(n)的所有可能性。情况1和情况2之间有一定的间隙, f ( n ) f(n) f(n)可能小于 n l o g b a n^{log_ba} nlogba但不是多项式意义上的小于。类似地,情况2和情况3之间也存在一定的间隙, f ( n ) f(n) f(n)可能大于 n l o g b a n^{log_ba} nlogba但不是多项式意义上的大于。如果函数 f ( n ) f(n) f(n)落在这两个间隙中,或者情况3中要求的正则条件不成立,就不能使用主方法来求解递归式。
使用主方法
先来看一个例子:
T
(
n
)
=
9
T
(
n
/
3
)
+
n
T(n)=9T(n/3)+n
T(n)=9T(n/3)+n
我们有
a
=
9
a=9
a=9,
b
=
3
b=3
b=3,
f
(
n
)
=
n
f(n)=n
f(n)=n,因此
n
l
o
g
b
a
=
n
l
o
g
3
9
=
Θ
(
n
2
)
n^{log_ba}=n^{log_39}=\Theta(n^2)
nlogba=nlog39=Θ(n2)。由于
f
(
n
)
=
O
(
n
l
o
g
3
9
−
ε
)
f(n)=O(n^{log_3{9-\varepsilon}})
f(n)=O(nlog39−ε),其中
ε
=
1
\varepsilon=1
ε=1,因此可以应用主定理的情况1,从而得到解
T
(
n
)
=
Θ
(
n
2
)
T(n)=\Theta(n^2)
T(n)=Θ(n2)。
再看例子:
T
(
n
)
=
T
(
2
n
/
3
)
+
1
T(n)=T(2n/3)+1
T(n)=T(2n/3)+1
其中
a
=
1
a=1
a=1,
b
=
3
/
2
b=3/2
b=3/2,
f
(
n
)
=
1
f(n)=1
f(n)=1,因此
n
l
o
g
b
a
=
n
l
o
g
3
/
2
1
=
n
0
=
1
n^{log_ba}=n^{log_{3/2}1}=n^0=1
nlogba=nlog3/21=n0=1。由于
f
(
n
)
=
Θ
(
n
l
o
g
b
a
)
=
Θ
(
1
)
f(n)=\Theta(n^{log_ba})=\Theta(1)
f(n)=Θ(nlogba)=Θ(1),因此应用情况2,从而得到解
T
(
n
)
=
Θ
(
l
g
n
)
T(n)=\Theta(lgn)
T(n)=Θ(lgn)
对于递归式:
T
(
n
)
=
3
T
(
n
/
4
)
+
n
l
g
n
T(n)=3T(n/4)+nlgn
T(n)=3T(n/4)+nlgn
其中
a
=
3
a=3
a=3,
b
=
4
b=4
b=4,
f
(
n
)
=
n
l
g
n
f(n)=nlgn
f(n)=nlgn,因此
n
l
o
g
b
a
=
n
l
o
g
4
3
=
O
(
n
0.793
)
n^{log_ba}=n^{log_43}=O(n^{0.793})
nlogba=nlog43=O(n0.793)。由于
f
(
n
)
=
Ω
(
n
l
o
g
4
3
+
ε
)
f(n)=\Omega(n^{log_4{3+\varepsilon}})
f(n)=Ω(nlog43+ε),其中
ε
≈
0.2
\varepsilon\approx0.2
ε≈0.2,因此,如果可以证明正则条件成立,即可应用情况3。当
n
n
n足够大时,对于
c
=
3
/
4
c=3/4
c=3/4,
a
f
(
n
/
b
)
=
3
(
n
/
4
)
l
g
(
n
/
4
)
≤
(
3
/
4
)
n
l
g
n
=
c
f
(
n
)
af(n/b)=3(n/4)lg(n/4)\le(3/4)nlgn=cf(n)
af(n/b)=3(n/4)lg(n/4)≤(3/4)nlgn=cf(n)。因此,由情况3,递归式的解为
T
(
n
)
=
Θ
(
n
l
g
n
)
T(n)=\Theta(nlgn)
T(n)=Θ(nlgn)。
主方法不能递归式:
T
(
n
)
=
2
T
(
n
/
2
)
+
n
l
g
n
T(n)=2T(n/2)+nlgn
T(n)=2T(n/2)+nlgn
虽然这个递归式看起来有恰当的形式:
a
=
2
a=2
a=2
b
=
2
b=2
b=2
f
(
n
)
=
n
l
g
(
n
)
f(n)=nlg(n)
f(n)=nlg(n),以及
n
l
o
g
b
a
=
n
n^{log_ba}=n
nlogba=n。你可能想到要用情况3,因为
f
(
n
)
=
n
l
g
n
f(n)=nlgn
f(n)=nlgn渐近大于
n
l
o
g
b
a
=
n
n^{log_ba}=n
nlogba=n。问题出在它并不是多项式意义上的大于。对任意正常数
ε
\varepsilon
ε,比值
f
(
n
)
/
n
l
o
g
b
a
=
(
n
l
g
n
)
/
n
=
l
g
n
f(n)/n^{log_ba}=(nlgn)/n=lgn
f(n)/nlogba=(nlgn)/n=lgn都渐近小于
n
ε
n^\varepsilon
nε。因此,递归式落入了情况2和情况3之间的间隙。
如果遇到不能用主方法解决的递归式,就要试着利用递归树或者代入法进行求解。具体的求解过程,可以参照算法导论第四章内容。