Hw5 Divide and Conquer
1 Nuts and Bolts
边界条件:当只有一个螺丝和一个螺母时,匹配螺丝和螺母。
Divide:
将螺丝集合记为
A
=
{
a
1
,
a
2
,
a
3
.
.
.
}
A=\set{a_1,a_2,a_3...}
A={a1,a2,a3...}
将螺母集合记为
B
=
{
b
1
,
b
2
,
b
3
.
.
.
}
B=\set{b_1,b_2,b_3...}
B={b1,b2,b3...}
- 先在螺丝集合 A A A 中,随机选中一个螺丝 a 1 a_1 a1,将 a 1 a_1 a1 与所有螺母 B B B 进行匹配,并将螺母分为 3 3 3 类:螺丝 > > > 螺母的放入集合 B 1 B_1 B1;螺母 > > > 螺丝的放入集合 B 2 B_2 B2;和 a 1 a_1 a1 匹配的螺母 b 1 b_1 b1。
- 再将 b 1 b_1 b1 与 除去螺丝 a 1 a_1 a1外的所有螺丝 A − { a 1 } A-\set{a_1} A−{a1} 相匹配,可将螺丝分为 2 2 2 类:螺母 > > > 螺丝的集合 A 1 A_1 A1;螺丝 > > > 螺母的集合 A 2 A_2 A2
至此,即将螺丝螺母分为以下几部分:
小 | 相匹配 | 大 | |
---|---|---|---|
螺丝 A A A | A 1 A_1 A1 | { a 1 } \set{a_1} {a1} | A 2 A_2 A2 |
螺母 B B B | B 1 B_1 B1 | { b 1 } \set{b_1} {b1} | B 2 B_2 B2 |
Conquer:递归地对 A 1 A_1 A1 和 B 1 B_1 B1、 A 2 A_2 A2 和 B 2 B_2 B2 进行匹配。
Merge:返回 A 1 A_1 A1 和 B 1 B_1 B1、 A 2 A_2 A2 和 B 2 B_2 B2的匹配结果以及匹配对 ( a 1 , b 1 ) (a_1, b_1) (a1,b1)。
复杂度:
- Divide 代价:
O
(
n
)
O(n)
O(n)
- 将 a 1 a_1 a1 与所有螺母 B B B 进行匹配 代价为: O ( n ) O(n) O(n)
- 将 b 1 b_1 b1 与 除去螺丝 a 1 a_1 a1外的所有螺丝 A − { a 1 } A-\set{a_1} A−{a1} 相匹配 代价为: O ( n ) O(n) O(n)
- Conquer 代价: T ( ∣ A 1 ∣ ) + T ( n − 1 − ∣ A 1 ∣ ) T(|A_1|)+T(n-1-|A_1|) T(∣A1∣)+T(n−1−∣A1∣),其中 ∣ A 1 ∣ |A_1| ∣A1∣ 为 0 , 1 , … , n − 1 0,1,…,n-1 0,1,…,n−1 的概率均为 1 n \frac{1}{n} n1
- Merge 代价:不计算
所以,总体代价为 O ( n l o g n ) O(nlogn) O(nlogn)。
2 Complex Number Multiplication
已知:
(
a
+
b
i
)
(
c
+
d
i
)
=
(
a
c
−
b
d
)
+
(
a
d
+
b
c
)
i
(a+bi)(c+di)=(ac-bd)+(ad+bc)i
(a+bi)(c+di)=(ac−bd)+(ad+bc)i
三次实数乘法为:
M
1
=
(
a
+
b
)
⋅
c
=
a
c
+
b
c
M_1=(a+b)\cdot c=ac+bc
M1=(a+b)⋅c=ac+bc
M
2
=
b
⋅
(
c
+
d
)
=
b
c
+
b
d
M_2=b\cdot (c+d)=bc+bd
M2=b⋅(c+d)=bc+bd
M
3
=
(
a
−
b
)
⋅
d
=
a
d
−
b
d
M_3=(a-b)\cdot d=ad-bd
M3=(a−b)⋅d=ad−bd
有:
实部:
M
1
−
M
2
M_1-M_2
M1−M2
虚部:
M
2
+
M
3
M_2+M_3
M2+M3
Closest-Pair Problem
1
蛮力解决:遍历 n n n 个点与剩余 n − 1 n-1 n−1 个点,计算点对距离,并更新最短距离,遍历完所有点对后即可求得最短点对距离。
复杂度: O ( n 2 ) O(n^2) O(n2)
2
边界条件:点集合 P P P 中仅含有 3 3 3 个点,返回最近点对。
Divide:
- 先找到 P P P 中 x x x坐标的中位数 x m x_m xm
- 用直线 l : x = x m l:x=x_m l:x=xm 将集合 P P P 分为左右两部分: P 1 P_1 P1 和 P 2 P_2 P2
Conquer:
- 递归地找到 P 1 P_1 P1 和 P 2 P_2 P2 中的最近点对:两个点对之间的距离为 d 1 d_1 d1 和 d 2 d_2 d2
- 记 d = min { d 1 , d 2 } d=\min\set{d_1,d_2} d=min{d1,d2}
Merge:
在点横坐标 x i x_i xi 满足 x m − d < x i < x m + d x_m-d<x_i<x_m+d xm−d<xi<xm+d 的临界区内(将满足要求的点集合记作 Q Q Q )
- 将点按照纵坐标 y i y_i yi 排序
- 对于 Q Q Q 中每一个点 q i q_i qi,寻找 Q Q Q 中:点纵坐标 y j y_j yj 满足 y i − d < y j ≤ y i y_i-d<y_j\leq y_i yi−d<yj≤yi 的点,集合记作 R i R_i Ri
- 计算 q i q_i qi 与 R i R_i Ri 中所有点的距离,并更新最短距离,直至 Q Q Q 中每一个点均被遍历
复杂度:
- Divide 代价: O ( n ) O(n) O(n)
- Conquer 代价: 2 T ( n 2 ) 2T(\frac{n}{2}) 2T(2n)
- Merge 代价: O ( n ) O(n) O(n)
所以根据主定理求解有:总代价 T ( n ) = O ( n l o g n ) T(n)=O(nlogn) T(n)=O(nlogn)
3
Kd-Tree算法
构建Kd-Tree:
- 在选择维度进行划分时,选择具有最大方差的维度,因为这意味着数据的分布较为分散,更容易划分。再选择该维度上所有数据的中值,将元素与中值进行比较,即可划分为两个子集合。同时创建一个树结点,用于存储划分维度和划分值。
- 对两个子集不断重复上述步骤直至不能再划分,将子集合中的数据保存到叶子结点。
查找最近邻:
- 找到每个叶子结点上保存的数据中距离最小值,并不断更新遍历。
- 再根据不同分支之间的距离与其比较,判断是否有不同分支的两点距离更近。
- 从下往上逐层进行回溯。