算法设计与分析课程复习笔记4——分治法
分治法
回顾:合并排序
分割、递归处理、合并
分治法
- 将一个问题分割成几个规模小、性质相同的独立的子问题
- 通常通过递归方法解决子问题
- 合并每个子问题的解得到整个问题的解
- 前提假设:原始问题的解能够通过子问题的求解获得
算法描述:
Solve(I)
n = size(I)
if (n <= smallsize)
solution = directlySolve(I);
else
divide I into I1, …, Ik.
for each i in {1, …, k}
Si = solve(Ii);
solution = combine(S1, …, Sk);
return solution;
为什么要采用分治法?
- 有时候它是最简单的方法
- 通常更有效
- 与其他方法的效率可能相同甚至更坏
- 必须分析分治算法的代价
- 不肯定是递归的
分治法的开销
- 分割开销
- 子问题解决开销
- 合并开销
形式:
T(n) = D(n) + Sum[ T(size(
I
i
I_i
Ii) ] + C(n)
更一般化:T(n) = a T(n/b) + f(n)
二分搜索
输入: 排序好的序列
a
0
a_0
a0,
a
1
a_1
a1, …,
a
n
−
1
a_{n-1}
an−1和数值X
思想:
将X与中值比较
左、右比较
规模逐渐减小
example:
3 7 11 12 15 19 24 33 41 55
24
↓
19 24 33 41 55
24
↓
19 24
24
二分搜索的时间复杂性
T
(
n
)
=
{
1
i
f
n
=
1
T
(
⌊
n
2
⌋
)
+
1
o
t
h
e
r
w
i
s
e
T(n)=\left\{ \begin{aligned} 1 ifn=1\\ T(\lfloor\frac n2\rfloor)+1 otherwise \end{aligned} \right.
T(n)=⎩⎨⎧1 ifn=1T(⌊2n⌋)+1 otherwise
矩阵乘法
Z
=
X
Y
Z=XY
Z=XY
X
,
Y
X,Y
X,Y均为n*n
时间开销:O(n3)
对于
X
X
X(n*m)
∗
*
∗
Y
Y
Y(m*q)的情况,开销O(nmq)
I
=
A
E
+
B
G
I=AE+BG
I=AE+BG
J
=
A
F
+
B
H
J=AF+BH
J=AF+BH
K
=
C
E
+
D
G
K=CE+DG
K=CE+DG
L
=
C
F
+
D
H
L=CF+DH
L=CF+DH
考虑:分割成8个(n/2)*(n/2)相乘和另外4个矩阵加
则
T
(
n
)
=
8
T
(
n
/
2
)
+
b
n
2
T(n) = 8T(n/2) + bn^2
T(n)=8T(n/2)+bn2
T
(
n
)
仍
然
是
Θ
(
n
3
)
T(n)仍然是Θ(n^3)
T(n)仍然是Θ(n3)
矩阵Strassen算法
如下定义
S
1
S_1
S1~
S
7
S_7
S7:
S
1
=
A
(
F
−
H
)
S_1=A(F-H)
S1=A(F−H)
S
2
=
(
A
+
B
)
H
S_2=(A+B)H
S2=(A+B)H
S
3
=
(
C
+
D
)
E
S_3=(C+D)E
S3=(C+D)E
S
4
=
D
(
G
−
E
)
S_4=D(G-E)
S4=D(G−E)
S
5
=
(
A
+
D
)
(
E
+
H
)
S_5=(A+D)(E+H)
S5=(A+D)(E+H)
S
6
=
(
B
−
D
)
(
G
+
H
)
S_6=(B-D)(G+H)
S6=(B−D)(G+H)
S
7
=
(
A
−
C
)
(
E
+
F
)
S_7=(A-C)(E+F)
S7=(A−C)(E+F)
I
=
S
5
+
S
6
+
S
4
−
S
2
I=S_5+S_6+S_4-S_2
I=S5+S6+S4−S2
J
=
S
1
+
S
2
J=S_1+S_2
J=S1+S2
K
=
S
3
+
S
4
K=S_3+S_4
K=S3+S4
L
=
S
1
−
S
7
−
S
3
+
S
5
L=S_1-S_7-S_3+S_5
L=S1−S7−S3+S5
现在
Z
=
X
Y
Z=XY
Z=XY只使用了7个递归相乘
T
(
n
)
=
7
T
(
n
/
2
)
+
b
n
2
T(n) = 7T(n/2) + bn^2
T(n)=7T(n/2)+bn2
通过主方式求解:
Θ
(
n
2.808
)
Θ(n^{2.808})
Θ(n2.808)
实例比较:
当我们将两个100*100的矩阵相乘时,n3是1000000,而n2.808是413048
实际上有更优秀的算法,可达到 Θ ( n 2.376 ) Θ(n^{2.376}) Θ(n2.376),n2.376仅为56494.(需另外查资料)
大整数相乘
时间开销:
Θ
(
n
2
)
Θ(n^2)
Θ(n2)
分治法:
X
=
a
∣
b
X= a | b
X= a ∣ b
Y
=
c
∣
d
Y= c | d
Y= c ∣ d
X
=
a
∗
2
n
/
2
+
b
X=a*2^{n/2}+b
X=a∗2n/2+b
Y
=
c
∗
2
n
/
2
+
d
Y=c*2^{n/2}+d
Y=c∗2n/2+d
X
Y
=
a
c
2
n
+
(
a
d
+
b
c
)
2
n
/
2
+
b
d
XY=ac2^n+(ad+bc)2^{n/2}+bd
XY=ac2n+(ad+bc)2n/2+bd
算法如下:
Mult(X,Y)
if|X|=|Y|=1 then do return XY
else return
Mult(a,c)2n+(Mult(a,d)+Mult(b,c))2n/2+Mult(b,d)
开销函数:
T
(
n
)
=
{
1
i
f
n
=
1
4
T
(
n
2
)
+
Θ
(
n
)
i
f
n
>
1
T(n)=\left\{ \begin{aligned} 1 ifn=1\\ 4T(\frac n2)+Θ(n) ifn>1 \end{aligned} \right.
T(n)=⎩⎨⎧1 ifn=14T(2n)+Θ(n) ifn>1
主方式法求解: Θ ( n 2 ) Θ(n^2) Θ(n2)
更好的方法(Karatsuba 1962)
利用高斯等式:
a
d
+
b
c
=
(
a
+
b
)
(
c
+
d
)
−
a
c
−
b
d
ad+bc=(a+b)(c+d)-ac-bd
ad+bc=(a+b)(c+d)−ac−bd
算法如下:
Mult(X,Y)
if|X|=|Y|=1 then do return XY
else
A
1
A_1
A1=Mult(a,c);
A
2
A_2
A2=Mult(b,d);
A
3
A_3
A3=Mult((a+b),(c+d));
return
A
1
2
n
+
(
A
3
−
A
1
−
A
2
)
2
n
/
2
+
A
2
A_12^n+(A_3-A_1-A_2)2^{n/2}+A_2
A12n+(A3−A1−A2)2n/2+A2
开销函数:
T
(
n
)
=
{
1
i
f
n
=
1
3
T
(
n
2
)
+
Θ
(
n
)
i
f
n
>
1
T(n)=\left\{ \begin{aligned} 1 ifn=1\\ 3T(\frac n2)+Θ(n) ifn>1 \end{aligned} \right.
T(n)=⎩⎨⎧1 ifn=13T(2n)+Θ(n) ifn>1
主方式求解: Θ ( n l o g 2 3 ) Θ(n^{log_23}) Θ(nlog23)= Θ ( n 1.58 ) Θ(n^{1.58}) Θ(n1.58)
最近点对问题
蛮力法:计算出两两之间的距离然后比较的方法
分治法求解
假设:各点x坐标互异,各点y坐标互异
在一维空间上求解:排列,从左到右求最小距离
1️⃣分割
2️⃣递归解决
3️⃣整合
L和R中是否各存在一点,它们之间的距离小于δ?
如果没有,结束。如果有,此类点对中距离最近的点即是整个问题的解。
4️⃣继续整合
只需考虑上图中带条S内的点的距离。S中的点最多要与S中的7个点进行比较。
算法如下:
ClosestPair(P)
Preprocessing:预处理,递增排列
Construct
P
x
P_x
Px and
P
y
P_y
Py as sorted-list by x- and y-coordinates
Divide:分割
Construct
L
L
L,
L
x
L_x
Lx,
L
y
L_y
Ly and
R
R
R,
R
x
R_x
Rx,
R
y
R_y
Ry
Conquer:治理
Let
δ
1
δ_1
δ1 = ClosestPair(
L
L
L,
L
x
L_x
Lx,
L
y
L_y
Ly)
Let
δ
2
δ_2
δ2 = ClosestPair(
R
R
R,
R
x
R_x
Rx,
R
y
R_y
Ry)
Combination:整合
Let δ = min(
δ
1
δ_1
δ1,
δ
2
δ_2
δ2)
Construct S and
S
y
S_y
Sy(按y坐标排序)
For each point in
S
y
S_y
Sy , check each of its next 7 points down the list(检查与后续7个点之间的距离)
If the distance is less than δ, update the δ as this smaller distance(如果存在小于δ的距离,则为距离最短点对)
时间开销:
预处理:
O
(
n
l
g
n
)
O(n lg n)
O(nlgn)
分割:
O
(
n
)
O(n)
O(n)
治理:
2
T
(
n
/
2
)
2T(n/2)
2T(n/2)
整合:
O
(
n
)
O(n)
O(n)
total: O ( n l g n ) O(n lg n) O(nlgn)
参考:任课教师邱德红教授的课件