最邻近点对问题(Closest-Pair Problem):三维的分治解法详解

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

这是该系列的第三篇。一维、二维的最邻近点对问题(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(xikxjk)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<

评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值