找到最接近的点集的最快方法

时间:2019-05-13 15:01:23

标签: python-3.x algorithm

我有三个点数组:

write

我需要最有效的方法来找到彼此最接近的三个点(每个阵列一个)(每个轴上一个像素以内)。

我现在正在做的事情是以一个要点作为参考,比如说A=[[5,2],[1,0],[5,1]] B=[[3,3],[5,3],[1,1]] C=[[4,2],[9,0],[0,0]] ,然后循环使用所有其他B和C点来寻找解决方案。如果A[0]没有结果,我将引用移至A[0],依此类推。这种方法是一个巨大的问题,因为如果我增加每个数组的点数和/或数组的数量,则需要太多的时间才能收敛,特别是如果解决方案在数组的最后一个成员中时。因此,我想知道是否有任何方法可以不用参考就可以做到这一点,或者比仅循环遍历所有元素更快捷的方法。

我必须遵循的规则如下:

  • 最终的解决方案只能由每个数组中的一个元素来完成,例如:A[1]
  • 每个选定元素必须在X和Y方向上与解决方案的所有其他成员相距1个像素之内(因此对于解决方案的每个成员,分别为S=[A[n],B[m],C[j]]Xi-Xj<=1)。

例如,在这种简化的情况下,解决方案将是:Yi-Yj<=1

为进一步阐明问题:我在上面写的内容只是一个简单的示例,用以解释我的需求。在我的真实情况下,我不知道列表的长度,也不知道我必须使用的列表数,可以是A,B,C或A,B,C,D,E ...(每个因此,我还需要找到一种使它尽可能通用的方法。

2 个答案:

答案 0 :(得分:3)

此要求:

  

每个选定元素必须在X和Y方向上与解决方案的所有其他成员相距1像素之内(因此对于解决方案的每个成员,分别为Xi-Xj<=1Yi-Yj<=1

大大简化了问题,因为这意味着对于任何给定( x i y i ) ,只有( x j y j )九种可能的选择。

所以我认为最好的方法如下:

  • B C 复制到setstuples中。
  • 遍历 A 。对于每个点( x i y i ):
    • x 的值从 x i -1迭代到 x i +1和 y 的值从 y i -1到 y i +1。对于每个结果点( x j y j ):
      • 检查( x j y j )是否在 B 中。如果是这样的话:
        • max x i x j )-1至min x i x j ) +1和max( y i y j y 的值)-1至min( y i y j )+ 1。对于每个结果点( x k y k ):
          • 检查( x k y k )是否在 C 中。如果是这样,我们就完成了!
  • 如果我们在没有比赛的情况下结束比赛,那意味着没有人了。

这大约需要 O (len( A )+ len( B )+ len( C ) )时间和 O (len( B )+ len( C )多余的空间。


编辑后添加(由于评论中有后续问题):如果您有 N 个列表而不是3个,则可以嵌套 N 循环深(在 N 中给出时间指数),您将需要执行以下操作:

  • 如上所述,将 B C 等复制到元组中。
  • 遍历 A 。对于每个点( x i y i ):
    • 创建一个包含( x i y i )及其八个邻居的集合。
    • 对于每个列表 B C 等:
      • 对于九个点集中的每个元素,请查看它是否在当前列表中。
      • 更新集合以删除当前列表中没有的任何点 在当前列表中没有任何邻居。
    • 如果集合中至少还包含一个元素,那么-太好了,每个列表都包含一个位于该元素一个像素内的点(所有这些点也都位于一个像素内)。因此,我们完成了!
  • 如果我们在没有比赛的情况下结束比赛,那意味着没有人了。

实现起来要复杂得多,但是在 N 中是线性的,而不是在 N 中是指数的。

答案 1 :(得分:0)

当前,您正在使用具有O(n2)复杂度的 bruteforce 算法找到解决方案。如果您的列表包含1000个项目,则您的算法将需要运行1000000次迭代...(tobias_k指出,甚至是O(n3))

就像在这里看到的一样:https://en.wikipedia.org/wiki/Closest_pair_of_points_problem,您可以使用分而治之算法对其进行改进,该算法将在O(n log n)时间内运行。

您应该搜索Delaunay triangulation和/或Voronoi diagram实现。

  

注意:如果可以使用外部库,则还应该考虑查看scipy库:https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.spatial.Delaunay.html