MIT算法导论03-分治法(Divide and Conquer)
课程名:Introduction to Algorithms
课程编号:6.046J/18.410J
授课教师:Prof.Erik Demame
分治法是本门课第一个算法设计方法
分治法将引出所有类型的递归。
分治法解决问题的步骤
-
Divide the problem (instance)
into one ore more subproblems -
Conquer each subproblem recursively
-
Combine solutions
应用实例
归并排序(merge sort)
时间复杂度
T
(
n
)
=
2
T
(
n
/
2
)
+
Θ
(
n
)
T(n)=2T(n/2)+\Theta(n)
T(n)=2T(n/2)+Θ(n)
二分查找(binary search)
递归式:
T
(
n
)
=
T
(
n
/
2
)
+
Θ
(
1
)
T(n)=T(n/2)+\Theta(1)
T(n)=T(n/2)+Θ(1)
时间复杂度
T
(
n
)
=
Θ
(
l
g
n
)
T(n)=\Theta(lgn)
T(n)=Θ(lgn)
乘方问题 Powering a number
given number x
integer
n
≥
0
n\ge0
n≥0 compute
x
n
x^n
xn
Naive algorithm
x
∗
x
∗
x
∗
⋯
∗
x
x*x*x*\cdots*x
x∗x∗x∗⋯∗x
T
(
n
)
=
Θ
(
n
)
T(n)=\Theta(n)
T(n)=Θ(n)
x n = { x n / 2 ∗ x n / 2 i f n e v e n x n − 1 ∗ x n − 1 ∗ x i f n o d d x^n=\left\{ \begin{array}{cl}x^{n/2}*x^{n/2}&if\,n\,even\\x^{n-1}*x^{n-1}*x&if\,n\,odd\end{array}\right . xn={xn/2∗xn/2xn−1∗xn−1∗xifnevenifnodd
T ( n ) = T ( n / 2 ) + Θ ( 1 ) = Θ ( l g n ) T(n)=T(n/2)+\Theta(1)=\Theta(lgn) T(n)=T(n/2)+Θ(1)=Θ(lgn)
斐波那契数列 Fibonacci numbers
- Naive recursive
F ( n ) = { 0 n = 0 1 n = 1 F ( n − 2 ) + F ( n − 1 ) n ≥ 2 F(n)=\left\{ \begin{array}{ll}0&n=0\\ 1&n=1\\ F(n-2)+F(n-1)&n\ge 2\end{array}\right . F(n)=⎩⎨⎧01F(n−2)+F(n−1)n=0n=1n≥2
T ( n ) = Ω ( φ n ) T(n)=\Omega(\varphi^n) T(n)=Ω(φn),其中 φ = 1.618 \varphi=1.618 φ=1.618为黄金分割数.
任何以多项式级为上限的算法就是好算法。-Jack Edmonds
-
bottom-up recursive algorithm
compute F 0 , F 1 , F 2 , ⋯ , F n F_0,F_1,F_2,\cdots,F_n F0,F1,F2,⋯,Fn
T ( n ) = Θ ( n ) T(n)=\Theta(n) T(n)=Θ(n) -
naive recursive squaring
F ( n ) = φ n / 5 F(n)=\varphi^n/\sqrt 5 F(n)=φn/5 rounded to nearest integer
现实中这种方法不可用,因为, φ \varphi φ和 5 \sqrt 5 5要用浮点数表示,算出来精确度会有损失。
实际上,在一台普通机器上,有些问题只能用指数时间的算法解决,而在一类理论机器上,可能可以在多项式时间内解决问题
- recursive squaring algorithm
Theorem [ F n + 1 F n F n F n − 1 ] = [ 1 1 1 0 ] n \begin{bmatrix}F_{n+1}&F_n\\F_n&F_{n-1}\end{bmatrix}=\begin{bmatrix}1&1\\1&0\end{bmatrix}^n [Fn+1FnFnFn−1]=[1110]n
T ( n ) = Θ ( l g n ) T(n)=\Theta(lgn) T(n)=Θ(lgn)
proof: by induction on n
Base:
[
F
2
F
1
F
1
F
0
]
=
[
1
1
1
0
]
2
\begin{bmatrix}F_{2}&F_1\\F_1&F_{0}\end{bmatrix}=\begin{bmatrix}1&1\\1&0\end{bmatrix}^2
[F2F1F1F0]=[1110]2
Assume: [ F n F n − 1 F n − 1 F n − 2 ] = [ 1 1 1 0 ] n − 1 \begin{bmatrix}F_{n}&F_{n-1}\\F_{n-1}&F_{n-2}\end{bmatrix}=\begin{bmatrix}1&1\\1&0\end{bmatrix}^{n-1} [FnFn−1Fn−1Fn−2]=[1110]n−1
Step: [ F n + 1 F n F n F n − 1 ] = [ 1 1 1 0 ] n − 1 [ 1 1 1 0 ] = [ 1 1 1 0 ] n \begin{bmatrix}F_{n+1}&F_n\\F_n&F_{n-1}\end{bmatrix}=\begin{bmatrix}1&1\\1&0\end{bmatrix}^{n-1}\begin{bmatrix}1&1\\1&0\end{bmatrix}=\begin{bmatrix}1&1\\1&0\end{bmatrix}^{n} [Fn+1FnFnFn−1]=[1110]n−1[1110]=[1110]n
QED
矩阵乘法 Matrix multiplication
Input:
A
=
[
a
i
j
]
,
B
=
[
b
i
j
]
A=[a_{ij}], B=[b_ij]
A=[aij],B=[bij]
i
,
j
=
1
,
2
,
⋯
,
n
i,j=1,2,\cdots,n
i,j=1,2,⋯,n
Output:
C
=
[
c
i
j
]
=
A
B
C=[c_ij]=AB
C=[cij]=AB
c
i
j
=
∑
k
=
1
n
a
i
k
b
k
j
c_{ij}=\sum\limits_{k=1}^na_{ik}b_{kj}
cij=k=1∑naikbkj
- Standard algorithms
T ( n ) = Θ ( n 3 ) T(n)=\Theta(n^3) T(n)=Θ(n3)
for i=1 to n
do for j=1 to n
c_ij=0
do for k=1 to n
do c_ij=c_ij+a_ik*b_kj
- Strassen’s algorithm
T
(
n
)
=
7
T
(
n
/
2
)
+
Θ
(
n
2
)
=
Θ
(
n
l
g
7
)
=
O
(
n
2
.
81
)
T(n)= 7T(n/2)+\Theta(n^2)=\Theta(n^{lg7})=O(n^2.81)
T(n)=7T(n/2)+Θ(n2)=Θ(nlg7)=O(n2.81)
尽管如此,这并不是最优算法,目前最优的算法大概是
Θ
(
n
2.376
)
\Theta(n^{2.376})
Θ(n2.376)
理论上Strassen’s algorithm快了一些,但是并不切实际,不要用这个。
超大规模集成电路 VLSI layout
Problem: Embed a complete binary tree
on n-leaves, in a grid with minimum area
顶点要放在网格点上,边组成正交路线,不能相交。
- naive embedding
L ( n ) = 2 L ( n / 4 ) + Θ ( 1 ) = Θ ( n ) L(n)=2L(n/4)+\Theta(1)=\Theta(\sqrt n) L(n)=2L(n/4)+Θ(1)=Θ(n), case 1