Divide & Conquer Algorithms
O(n log n) Algorithm for Counting Inversions
- 分治算法
- 将问题分割为更小的子问题
- 通过递归调用解决这些问题
- 将子问题的结果合并到更大的子问题中作为其结果
- 逆序对
- 数组中存在的
i < j
但是a[i] > a[j]
的情况 - 左逆序对:二者都在左半部分
- 右逆序对:二者都在右半部分
- 跨逆序对:分别在两侧
- 数组中存在的
- 思路:将归并排序融合进来
- 两个半部分一边数逆序对一边排序,对两个有序的半部分再归并同时计算逆序对
- 归并时,对于右侧的一个数字y,若复制到目标数组时,其相关的逆序对个数即此时左侧剩下的元素个数
- 因为整个过程基于归并排序,因此与归并排序有着相同的时间复杂度( O ( n log n ) O(n \log n) O(nlogn))
Strassen’s Subcubic Matrix Multiplication
- 直接计算矩阵:立方级别时间复杂度
- 递归算法:
- 将矩阵等分成四个部分
- 将两个矩阵的乘积转化为八个小矩阵的乘积(八个递归项)
- 做加和处理
- 仍旧是立方复杂度
- Steassen算法
- 递归项只有7个
- 进行必要的加和和相减处理
- 八个小矩阵为A~H
- 递归计算七个积:
- P 1 = A ( F − H ) P_1=A(F-H) P1=A(F−H)
- P 2 = ( A + B ) H P_2=(A+B)H P2=(A+B)H
- P 3 = ( C + D ) E P_3=(C+D)E P3=(C+D)E
- P 4 = D ( G − E ) P_4=D(G-E) P4=D(G−E)
- P 5 = ( A + D ) ( E + H ) P_5=(A+D)(E+H) P5=(A+D)(E+H)
- P 6 = ( B − D ) ( G + H ) P_6=(B-D)(G+H) P6=(B−D)(G+H)
- P 7 = ( A − C ) ( E + F ) P_7=(A-C)(E+F) P7=(A−C)(E+F)
- X + Y = ( A E + B G A F + B H C E + D G C F + D H ) = ( P 5 + P 4 − P 2 + P 6 P 1 + P 2 P 3 + P 4 P 1 + P 5 − P 3 − P 7 ) X+Y = (\begin{matrix}AE+BG & AF+BH \\ CE+DG & CF+DH\end{matrix}) = (\begin{matrix} P_5+P_4-P_2+P_6 & P_1+P_2 \\ P_3+P_4 & P_1+P_5-P_3-P_7 \end{matrix}) X+Y=(AE+BGCE+DGAF+BHCF+DH)=(P5+P4−P2+P6P3+P4P1+P2P1+P5−P3−P7)
- 有效地降低了复杂度(次立方级别复杂度)
Closet Pair
- 最近点对问题:
- 给出一组平面上的点
- 找出其中距离最近的一对
- 距离为点的欧氏距离
- 假设所有点坐标不同(相同亦可)
- 暴力搜索: θ ( n 2 ) \theta(n^2) θ(n2)的时间复杂度
- 1-D平面上的点:归并排序后遍历相邻点的距离( O ( n log n ) O(n \log n) O(nlogn))
- 基本思路:类似逆序对算法,进行归并式的寻找,时间复杂度同样为( O ( n log n ) O(n \log n) O(nlogn))
- 关键思路:只计算尚未“解锁”的情形中距离比现有递归结果最小的部分
- 计算过程
- 将点按照坐标的从大到小排序,将Q和R表示为点集的左半部分和右半部分
- 计算(p1,q1)为Q中最近对
- 计算(p2,q2)为P中最近对
- 计算两个对的最小者的距离δ
- 根据δ和P,计算跨两部分的最近对(p3,q3)
- 取三者最小向上递归结果
- split最近对的寻找:线性时间扫描
- 一次只看7个点(已经按照y坐标排序)
The Master Method
- 对分治算法的数学分析:循环表示法(Recurrence)
- 循环表示法的形式化表示(假设子问题的大小均一致):
- 基本情形:对足够小的 n n n, T ( n ) ≤ a constant T(n) \le \text{a constant} T(n)≤a constant
- 对其他更大的
n
n
n:
T
(
n
)
≤
a
T
(
n
b
)
+
O
(
n
d
)
T(n) \le aT(\frac nb) + O(n^d)
T(n)≤aT(bn)+O(nd)
- a:递归调用的个数
- b:输入大小的缩减因子
- d:对递归调用结果的加和操作的指数因子
- 如果 a = b d a=b^d a=bd: T ( n ) = ( n d log n ) T(n)=(n^d \log n) T(n)=(ndlogn)
- 如果 a < b d a < b^d a<bd: T ( n ) = ( n d ) T(n)=(n^d) T(n)=(nd)
- 如果 a > b d a > b^d a>bd: T ( n ) = ( n log b a ) T(n)=(n^{\log_b a}) T(n)=(nlogba)