从O(nlogn)时间中的一组n个点中获取前k个最接近的点对?

时间:2019-03-04 19:47:22

标签: algorithm recursion data-structures closest-points

是否有可能比O(n^2)更快地在n个点集中找到 k对点?

我知道我可以计算O(nlogn)中最接近的点对,但是使用该算法,并不是所有距离都被计算出来,因此我无法返回前 k个最接近的点对点。

如果使用“ 蛮力”方法计算点的所有边的距离,此问题将变得微不足道,但这的复杂度为[n * (n-1)]/2,我想找到更有效的东西。

编辑: 在这里查看最接近的对算法: https://www.geeksforgeeks.org/closest-pair-of-points-using-divide-and-conquer-algorithm/

1 个答案:

答案 0 :(得分:0)

小型k的一个可行选择是在原始点集的子集上重复使用O(nlogn)算法,并随即删除点。更具体地说,保留形成最小对的一组点。每次查询下一个最接近的对时,我们都会查询这些点内以及每个点与其余原始点之间的下一个最接近的对,并取两对中的最接近的对。

首先,从原始集合中除去所有这些点之一,然后计算最接近的对。对“最小集”中的每个点重复此操作,并保持整体上最接近的对。当“最小集”的大小为O(j*nlogn)时,这将花费j的时间进行计算。

然后,在大小为O(1)的最小-最大堆上,通过find-min(k时间)在此“ min set”中查询下一个最接近的对。将点添加到我们的“最小集”中。每次将点添加到“最小集”时,我们都会计算“最小集”(大小j)中的每个点与这些(最多)2个新点之间的距离,将其插入到最小集中。最大堆,然后根据需要删除尽可能多的元素,以在k时再次使堆大小2j(最多O(jlogk)个元素)。

现在,我们采用这两个中的最接近的一对(如果相关,则从堆中删除-O(logk)时间),将这些点添加到我们的“最小集”中,并按照所述更新最小-最大堆,然后重复其余k-j个最接近的对。总体而言,这将花费O((k^2)nlogn + (k^2)logk + klogk) = O((k^2)(nlogn + logk)) = O((k^2)nlogn)时间。