这是该系列的第三篇。一维、二维的最邻近点对问题(Closest-Pair Problem):戳这里
PS:建议先快速浏览低维的分治解法,因为各维度的解决思路具有高度的关联性。如果还没有弄清二维解法仍要执意往下看,最好先给头发买好保险。
1 问题描述
对于三维点 p i = ( x i 1 , x i 2 , x i 3 ) p_i = (x_{i1}, x_{i2}, x_{i3}) pi=(xi1,xi2,xi3),任意两点的欧几里得距离为 ∑ k = 1 3 ( x i k − x j k ) 2 \sqrt{\sum_{k=1}^3(x_{ik} - x_{jk})^2} ∑k=13(xik−xjk)2。
暴力算法与二维完全一致,枚举所有可能的点对,计算距离并选择最小距离的点对返回。它的时间复杂度是 O ( n 2 ) O(n^2) O(n2)。
同样,借助分治思想可以把复杂度降到 O ( n l o g n ) O(nlogn) O(nlogn)。
2 算法描述
2.1 开始前
首先对于一个乱序的点集 P P P,我们需要分别对 x x x和 z z z进行排序,得到 P x P_x Px和 P z P_z Pz。前者用于divide,后者用于merge。不对 y y y进行排序的原因是,我们将通过切片来减少这个维度上的重复工作。
2.2 Divide步骤
这一步与二维情况完全一致,只不过按 y y y的情况变为了按 z z z。如理解二维的Divide,可跳过。
第一步:拆分
对于任意的点集 P P P,其中点的数量 ∣ P ∣ = n \vert P\vert = n ∣P∣=n,类似于二维情况,记 ⌊ n / 2 ⌋ \lfloor n/2\rfloor ⌊n/2⌋为 m i mi mi,可以在 P x P_x Px中第 m i mi mi个点的坐标(记为 x ∗ x^* x∗)处,将其分为 Q Q Q区与 R R R区。其中坐标小于等于 x ∗ x^* x∗的点放入 Q Q Q区,大于的点放入 R R R区。
准确来说,分区的标准是点在 P x P_x Px中的位置,小于等于 m i mi mi划入 Q Q Q区,反之 R R R区,不过按 x ∗ x^* x∗来理解会比较方便。
第二步: 维护有序数组
对于 Q Q Q区和 R R R区,我们想要维护4个有序数组:按 x x x或 z z z排好序的 Q x Q_x Qx, Q z Q_z Qz, R x R_x Rx, R z R_z Rz。其中,按 x x x排序的数组, Q x Q_x Qx和 R x R_x Rx,按索引就可以分开了。
而 Q z Q_z Qz和 R z R_z Rz,需要新建数组,顺次遍历 P z P_z Pz并判断从属的区域来构建,花费 O ( n ) O(n) O(n)时间,且它们自然就是有序的。注意,如果你想通过 Q x Q_x Qx和<

本文详细介绍了三维空间中最邻近点对问题的高效算法,通过分治策略将复杂度降至O(nlogn),包括关键步骤如Divide、Merge的具体实现及分析,附带Java代码示例。
最低0.47元/天 解锁文章
2324





