Archipelago

Lec 2分治法:中位数查找与凸包

讲义完成更新于 2026-09-17

Lec 2 分治法:中位数查找与凸包(Divide & Conquer: Median Finding & Convex Hull)

TL;DR

  • 分治范式与递推:分治法三步曲(划分、递归求解、合并),通过主定理精确界定递归树深度与各层工作量的平衡关系。
  • 确定性线性选择(BFPRT):通过“五分中位数”(Median of Medians)选定主元,确保每次递归至少剪除 3/103/10 的搜索空间,实现 T(n)≤T(n/5)+T(7n/10)+O(n)=O(n)T(n) \le T(n/5) + T(7n/10) + O(n) = O(n) 的严格最坏线性时间。
  • Karatsuba 大整数乘法:巧妙利用一次代数恒等变形将 4 次半长整数乘法降为 3 次,将经典多项式乘法复杂度由 O(n2)O(n^2) 打破至 O(nlog⁡23)≈O(n1.585)O(n^{\log_2 3}) \approx O(n^{1.585})。
  • 凸包分治构造:平面点集按横坐标二分,递归求得左右凸包后,通过双指针双向旋转在 O(n)O(n) 时间内找到公切线合并,达到与基于排序下界匹配的 O(nlog⁡n)O(n \log n) 复杂度。

分治法核心范式与主定理

分治(Divide and Conquer)是算法设计中最基础且强大的思维范式之一,标准执行流程包含三个阶段:

  1. 分解(Divide):将原问题划分为若干规模较小但结构相同的子问题;
  2. 解决(Conquer):递归求解各个子问题。当子问题足够小时直接求解(递归基);
  3. 合并(Combine):将各个子问题的解答合并为原问题的完整解。

主定理(Master Theorem)

对于形如 T(n)=aT(n/b)+f(n)T(n) = a T(n/b) + f(n) 的递归式(其中 a≥1,b>1a \ge 1, b > 1 为常数),设临界指数为 log⁡ba\log_b a:

  • 情况 1(叶节点支配):若存在 ϵ>0\epsilon > 0 使得 f(n)=O(nlog⁡ba−ϵ)f(n) = O(n^{\log_b a - \epsilon}),则 T(n)=Θ(nlog⁡ba)T(n) = \Theta(n^{\log_b a});
  • 情况 2(各层均衡):若 f(n)=Θ(nlog⁡balog⁡kn)f(n) = \Theta(n^{\log_b a} \log^k n)(k≥0k \ge 0),则 T(n)=Θ(nlog⁡balog⁡k+1n)T(n) = \Theta(n^{\log_b a} \log^{k+1} n);
  • 情况 3(根节点支配):若存在 ϵ>0\epsilon > 0 使得 f(n)=Ω(nlog⁡ba+ϵ)f(n) = \Omega(n^{\log_b a + \epsilon}) 且满足正则性条件,则 T(n)=Θ(f(n))T(n) = \Theta(f(n))。

中位数与顺序统计量:确定性线性时间选择(BFPRT)

问题定义

定义

顺序统计量(Order Statistic) 给定包含 nn 个互异元素的集合 SS 与整数 i∈{1,2,…,n}i \in \{1, 2, \dots, n\},求 SS 中第 ii 小的元素(即秩 rank(x)=i\mathrm{rank}(x) = i 的元素)。 当 i=⌊(n+1)/2⌋i = \lfloor (n+1)/2 \rfloor 时,该元素即为中位数(Median)。

若先对全量元素排序再按索引访问,时间复杂度为 O(nlog⁡n)O(n \log n)。若采用快速选择算法(QuickSelect),通过随机选取主元(Pivot)期望可在 O(n)O(n) 内完成,但最坏情况下仍可能退化至 O(n2)O(n^2)。

能否在最坏情况下依然保证 O(n)O(n) 确定性时间?Blum、Floyd、Pratt、Rivest 与 Tarjan 在 1973 年给出了划时代的 BFPRT 算法。

算法步骤与五分中位数策略

为了防止快速排序划分时出现极端倾斜,算法必须确定性地构造出一个“足够居中”的主元 xx:

  1. 分组:将 nn 个元素划分为 ⌊n/5⌋\lfloor n/5 \rfloor 个大小为 5 的子组,若有剩余(n mod 5n \bmod 5 个元素),单独作为一组;
  2. 求组内中位数:对每个大小为 5 的子组进行排序(每组至多 7 次比较,耗时 O(1)O(1)),取出每组的中位数,共得到 ⌈n/5⌉\lceil n/5 \rceil 个中位数;
  3. 递归求中位数的中位数:递归调用选择算法,找出这 ⌈n/5⌉\lceil n/5 \rceil 个组内中位数的中位数,记为主元 xx;
  4. 主元划分:以 xx 为基准将原集合划分为三个集合:
    • L={y∈S∣y<x}L = \{y \in S \mid y < x\}
    • E={y∈S∣y=x}E = \{y \in S \mid y = x\}
    • G={y∈S∣y>x}G = \{y \in S \mid y > x\}
  5. 递归分支收敛:
    • 若 i≤∣L∣i \le |L|,则在 LL 中递归寻找第 ii 小元素;
    • 若 ∣L∣<i≤∣L∣+∣E∣|L| < i \le |L| + |E|,直接返回 xx;
    • 若 i>∣L∣+∣E∣i > |L| + |E|,则在 GG 中递归寻找第 i−∣L∣−∣E∣i - |L| - |E| 小元素。

空间剪枝与复杂度推导

定理

BFPRT 主元平衡界 由 BFPRT 算法选出的主元 xx,至少大于原数组中的 3n/10−63n/10 - 6 个元素,且至少小于原数组中的 3n/10−63n/10 - 6 个元素。

证明: 考虑步骤 2 中获得的全部组内中位数。在这 ⌈n/5⌉\lceil n/5 \rceil 个中位数中,至少有一半(即 12⌈n/5⌉≥n10\frac{1}{2}\lceil n/5 \rceil \ge \frac{n}{10} 个)小于等于 xx。 在每一个中位数小于等于 xx 的 5 元组中,除了该组中位数自身之外,还有 2 个元素小于等于该中位数,因而至少有 3 个元素小于等于 xx。

排除掉主元自身所在组以及可能不足 5 个元素的剩余组,严格小于等于 xx 的元素数量至少为:

3(⌈12⌈n5⌉⌉−2)≥3(n10−2)=3n10−63 \left( \left\lceil \frac{1}{2} \left\lceil \frac{n}{5} \right\rceil \right\rceil - 2 \right) \ge 3 \left( \frac{n}{10} - 2 \right) = \frac{3n}{10} - 6

同理,严格大于等于 xx 的元素数量也至少为 3n/10−63n/10 - 6。

由此可得,在最坏情况下,进入步骤 5 递归的子问题规模上限为:

max⁡(∣L∣,∣G∣)≤n−(3n10−6)=7n10+6\max(|L|, |G|) \le n - \left( \frac{3n}{10} - 6 \right) = \frac{7n}{10} + 6

递归式求解:为什么必须是 5?

整体算法的运行时间递归关系为:

T(n)≤T(⌈n5⌉)+T(7n10+6)+O(n)T(n) \le T\left(\left\lceil \frac{n}{5} \right\rceil\right) + T\left(\frac{7n}{10} + 6\right) + O(n)

我们使用代入法证明 T(n)≤cnT(n) \le c n。设常数项满足 O(n)≤c0nO(n) \le c_0 n:

T(n)≤c(n5+1)+c(7n10+6)+c0n=c(9n10+7)+c0n=cn−(cn10−7c−c0n)T(n) \le c \left(\frac{n}{5} + 1\right) + c \left(\frac{7n}{10} + 6\right) + c_0 n = c \left(\frac{9n}{10} + 7\right) + c_0 n = c n - \left( \frac{c n}{10} - 7c - c_0 n \right)

只要取足够大的常数 cc(例如当 n≥140n \ge 140 时),括号内项恒为正,即可保证 T(n)≤cn=O(n)T(n) \le c n = O(n)。

我的理解

思考:为什么不用 3 分组? 若将元素按 3 个一组划分,主元递归项为 T(n/3)T(n/3),剩余递归项至多包含 n−2(n/6)=2n/3n - 2(n/6) = 2n/3 个元素。此时递推式为:

T(n)=T(n/3)+T(2n/3)+O(n)T(n) = T(n/3) + T(2n/3) + O(n)

由于 1/3+2/3=11/3 + 2/3 = 1,递归树每一层的总代价均为 O(n)O(n),树深为 O(log⁡n)O(\log n),整体复杂度退化为 O(nlog⁡n)O(n \log n)! 因此,5 是保证子问题规模系数和严格小于 1(1/5+7/10=9/10<11/5 + 7/10 = 9/10 < 1)的最小奇数。


大整数乘法:Karatsuba 算法

给定两个各包含 nn 位的大整数 AA 与 BB,计算乘积 A×BA \times B。经典逐位相乘算法需要 O(n2)O(n^2) 次位运算。

将两数按二进制高低位拆半:

A=2n/2X+Y,B=2n/2W+ZA = 2^{n/2} X + Y, \quad B = 2^{n/2} W + Z

展开式包含 4 个规模为 n/2n/2 的子乘法:

A×B=2n(XW)+2n/2(XZ+YW)+(YZ)A \times B = 2^n (XW) + 2^{n/2} (XZ + YW) + (YZ)

若直接递归,递推关系为 T(n)=4T(n/2)+O(n)T(n) = 4T(n/2) + O(n)。由主定理,nlog⁡24=n2n^{\log_2 4} = n^2,并未改善复杂度。

巧妙的恒等式变换

1962 年,苏联数学家 Anatoli Karatsuba 发现交叉项可以通过一次乘法与减法复用求得:

XZ+YW=(X+Y)(W+Z)−XW−YZXZ + YW = (X + Y)(W + Z) - XW - YZ

因此,只需递归计算 3 次半长乘法:

  1. P1=XWP_1 = XW
  2. P2=YZP_2 = YZ
  3. P3=(X+Y)(W+Z)P_3 = (X + Y)(W + Z) 交叉项即为 P3−P1−P2P_3 - P_1 - P_2。

递归式转变为:

T(n)=3T(n/2)+O(n)T(n) = 3T(n/2) + O(n)

应用主定理,临界指数为 log⁡23≈1.585\log_2 3 \approx 1.585。因此:

T(n)=Θ(nlog⁡23)≈Θ(n1.585)T(n) = \Theta(n^{\log_2 3}) \approx \Theta(n^{1.585})

这一跨越标志着代数复杂度突破二次瓶颈的里程碑,并进一步启发了基于 FFT 的 Schönhage-Strassen 算法。


计算几何:二维凸包的分治构造

定义

凸包(Convex Hull) 给定平面点集 PP,包含 PP 中所有点的最小凸多边形称为 PP 的凸包,记为 CH(P)\mathrm{CH}(P)。

分治法求解步骤

  1. 预排序:将全部点按 xx 坐标递增排序(若 xx 相同则按 yy 坐标递增),耗时 O(nlog⁡n)O(n \log n);
  2. 二分划分:取中位数垂线,将点集平分为左半部分 AA 与右半部分 BB;
  3. 递归求解:分别递归求出 CH(A)\mathrm{CH}(A) 与 CH(B)\mathrm{CH}(B);
  4. 公切线合并:在 O(n)O(n) 时间内寻找连接两凸包的上公切线与下公切线,并删除被切线包围的内部点链。

双指针寻找公切线

以求上公切线为例:

  • 分别从 AA 中最右侧的点 uu 与 BB 中最左侧的点 vv 开始,连接线段 (u,v)(u, v);
  • 检查线段 (u,v)(u, v) 是否位于凸包上方:
    • 若 AA 中存在点位于有向线段 (u,v)(u, v) 上方,将 uu 沿 AA 的逆时针方向移动一步;
    • 若 BB 中存在点位于有向线段 (u,v)(u, v) 上方,将 vv 沿 BB 的顺时针方向移动一步;
    • 重复上述交替检查与单调旋转,直到线段 (u,v)(u, v) 完全悬空在两凸包之上。

由于凸多边形的凸性,每个顶点在旋转过程中至多被访问常数次,寻找公切线的时间为 O(∣A∣+∣B∣)=O(n)O(|A| + |B|) = O(n)。

渐近复杂度

合并步骤仅需线性时间,故递归式为:

T(n)=2T(n/2)+O(n)=O(nlog⁡n)T(n) = 2T(n/2) + O(n) = O(n \log n)

由于平面凸包问题可通过反向归约将数值排序嵌入其中(xi↦(xi,xi2)x_i \mapsto (x_i, x_i^2)),在基于比较的模型下,凸包计算的复杂度下界为 Ω(nlog⁡n)\Omega(n \log n),因此分治算法达到理论最优渐近界。


我的理解

分治算法不仅是“拆分子问题递归”,其精髓在于重塑合并与剪枝的代数结构:

  1. 主定理指导下的几何平衡:BFPRT 算法告诉我们,只要能以线性代价确定性地丢弃常数比例(哪怕只是 3/103/10)的候选集,几何级数衰减就会以 1/(1−c)1/(1-c) 的形式将整体复杂度锁定在线性。
  2. 乘法与加法的代价置换:Karatsuba 的伟大之处在于洞察了加法与乘法计算成本的异构性——位加法是 O(n)O(n),而位乘法是 O(n2)O(n^2)。牺牲两次廉价的线性加法来削减一次昂贵的二次乘法,使得分治树的分支因子从 4 降至 3。
  3. 几何拓扑的单调性支撑:凸包合并之所以能在线性时间内收敛,核心在于凸性的“极角单调性”。分治保证了左右点集在空间上的天然分离,公切线查找如同滑动双指针,将原本难以处理的全局凸包更新降维至局部邻域的切线逼近。 :::