Algorithm 从给定的n个点中选择最近的k个点

Algorithm 从给定的n个点中选择最近的k个点,algorithm,language-agnostic,geometry,computational-geometry,Algorithm,Language Agnostic,Geometry,Computational Geometry,你在平面上有一组n个点,你可以在恒定的时间内计算任意一对点之间的距离。选择一个称为C的U子集,使C中正好有k个点,并且对于给定的k,C中最远的2个点之间的距离尽可能小。1a/2。现在再看三张

你在平面上有一组n个点,你可以在恒定的时间内计算任意一对点之间的距离。选择一个称为C的U子集,使C中正好有k个点,并且对于给定的k,C中最远的2个点之间的距离尽可能小。1
For each point in U
    make a list of the distance to each point in U
    sort the list
    add largest distance to a max-heap.
while any of the lists have more than k elements
    remove max of heap twice
    remove corresponding elements from the two lists they came from
    add the two newly exposed largest elements from those two lists to the heap
Any of the lists left with k elements will list the elements in C
基本上,找到两个点,这两个点看起来可能都在子集中,并且具有最大的成对距离,然后排除它们都在子集中。重复此操作,直到只剩下一种可能的方法来形成k大小的子集


这应该是时间复杂度O((n^2)log(n))和空间复杂度O(n^2)。

如果没有太多异常值,这应该是一个很好的近似解决方案

p = mean center (average x, y) of U
M = U sorted by distance to p
C = M[0:k]

因为这是一个面试问题,所以我想提出一个解决方案。(正如dcn在下面指出的,这并不能保证返回最优的解决方案,尽管它仍然应该是一个不错的启发式。好的捕获,dcn!)

  • 创建具有单点P的集合Sp
  • 计算Sp中的每个点与其外部的每个点之间的距离,然后将最大距离最小的点添加到Sp
  • 重复2。直到Sp有k点
  • 使用每个点重复1-3次作为初始P。取最大距离最小的Sp
  • Sp中有O(k)个点,Sp外有O(n)个点,因此找到最大距离最小的点是O(nk)。我们重复这个过程k次,然后重复整个过程n次,总体复杂度为O(n2k2)

    我们可以通过缓存Sp中的任意点与Sp外部的每个点之间的最大距离来改善这一点。如果
    maxDistanceFromPointInS[pointOutsideS]
    是一个O(1)哈希表,其中包含每个点
    pointOutsideS
    与Sp内部某个点之间的当前最大距离,然后每次我们添加一个新点时,我们为Sp之外的所有点设置最大距离(maxDistanceFromPointInS[p],距离(newPoint,p))。然后找到最小的最大距离是O(n),向Sp添加一个点是O(n)。重复这k次,我们得到O((n+n)k)=O(nk)。最后,我们将整个过程重复n次,总体复杂度为O(n2k)

    我们可以改进使用堆查找到O(1)的最小最大距离,但这不会改变总体复杂性


    顺便说一句,我花了一个小时才把这些都写下来——我不可能在采访中做到这一点。

    显然这是可行的

    但我不明白他们的算法。他们选择的圆圈似乎总是一个输入点。有人能解释一下这一点,或者清楚地解释一下他们做了什么(仅第2节就足够了)

    解决方案如-Aggarwal,1991所示。 其中描述的算法具有运行时间:
    O(k^2.5n log k+n log n)

    对于无法访问该文件的用户: 这个问题称为k-直径,定义为

    找到一组具有最小直径的k点。集合的直径是集合中任意点之间的最大距离


    我无法对所提出的算法进行概述,但它包括计算点的(3k-3)阶Voronoi图,然后解决每个O(kn)Voronoi集的问题(通过计算一些二部图中的最大独立集)。。。我想我想说的是,这是非常不平凡的,远远超出了采访和这个网站:-)

    所问的实际问题似乎很难。如果点不在平面内且具有任意距离,则从k-团归约将是NP困难的(取任意未加权图,为缺失边添加长度为无穷大的边,为现有边添加长度为1的边——只要“最近的k点”的最大相互距离为1而不是无穷大,就存在大小为k的团).然而,由于点被限制在平面内,因此禁止使用此类距离标签,因此可能存在解决方案。至少,它似乎适合于近似

    如果您的面试是指“包围k点的最小直径圆”,那么以下可能是您在面试中合理提出的最快的正确算法:

    对于每组尺寸3,计算包含这些点的最小圆,并检查每个点是否包含在此圆中。如果包含的数字至少为k,则相应地更新最小直径


    本质上,这是一个四重嵌套的for循环,因此运行时间是O(n^4).

    近似解永远都不够好。这一个肯定会失败。@Snowbear:我不想成为教你NP完全问题的人……近似解是一个棘手的陷阱,因为你必须证明它们的误差范围和运行时间。你当然可以在现实生活中做其他优化,比如查找群集等CGreedy算法m不起作用,因为您可能最终选择C={x,y1,y2}当x-y1和x-y2的距离很小,但y1和y2彼此距离很远时,谢谢你的指点-这不是我问过的面试问题,但我在考虑是否应该问,至少看看他们是怎么想的。@wrick:你会怎么回答这个问题?我认为问一个你自己无法回答的问题是不公平的……@ BLeReja-这就是为什么我在这里希望它可能有一个简单的解决方案,我没有想到。现在我已经改变了主意,决定不这样问:为什么最小k包围圈是不同的:考虑一个等边三角形的边长度A。包含所有3个端点的最小圆的半径r=3a/sqrt(a)>a/2。现在再看三张