我必须从给定集合中找出平面中所有最接近的点对。
我已经成功实现了类似于此伪代码功能的朴素算法O(n²)
,其中set
是输入中所有点的列表,count
是输入中所有点的计数,返回dist
,这是找到的最小距离,而result
是具有该距离的所有点对的列表。
function naive(Points[] set, int count)
result = []
distance = INF
for i=0 to count-1:
for j=i+1 to count:
newDistance = distance(set[i], set[j])
if newDistance < distance:
result = []
result.append({set[i], set[j]})
else if newDistance == distance:
result.append({set[i], set[j]})
return (dist, result)
此解决方案效果很好,但是由于O(n²)
的复杂性很高,因此对于较大的输入来说非常慢。我想找到一个更快,更优化的解决方案,因此我使用了基于this article的递归分治算法来实现O(n logn)
的解决方案,该算法适用于大多数输入,但是由于这种方法确实可以不要遍历像这样的输入失败的所有点(成对的顺序和成对的点的顺序无关紧要):
Input:
{A[0,0], B[1,0], C[1,1] D[0,1]}
Current (wrong) output:
{A[0,0], D[0,1]}, {B[1,0], C[1,1]}
Desired output:
{A[0,0], B[0,1]}, {A[0,0], D[0,1]}, {C[1,1], B[1,0]}, {C[1,1], D[1,0]}
,并且由于它是递归的,因此对于较大的输入,堆栈很容易溢出。解决此问题的更好方法是什么?
谢谢
答案 0 :(得分:1)
但是您不需要将所有内容与其他所有内容进行比较。对于任何给定的点对,想象它们都位于矩形的[与坐标轴对齐的矩形]对角线上,长度为d
。
x = d
行左侧的任何其他点都将更远,因此不应考虑。y = d
行下方的任何其他点都将更远,因此不应考虑。x = d
行右侧的任何其他点都将更远,因此不应考虑。y = d
行下方的任何其他点都将更远,因此不应考虑。可以想象类似的约束在每种情况下都会为您提供一个边界框,除非您的星座特别密集,否则该边界框应可消除内部循环中要考虑的大部分点。
您肯定需要在这里进行大量的动态编程,以便为大型设备提供合理的运行时间。
答案 1 :(得分:0)
最佳解决方案可能取决于点的分布方式。一种方法是将正方形分割成许多较小的子正方形,并选择每个子正方形平均约有1个点。接下来,将点与相应的子正方形相关联。最后,对于任何给定的点,您只需考虑最近的子正方形即可找到最近的邻居(通过检查所有可能包含较近点的子正方形来确认Nearesr状态)。
答案 2 :(得分:0)
关于第一个问题。我可能会误会,但我可以给您一些提示。
假设您有1000分。将它们按250点分成4组,然后在所有组对中组成500个元素集。总计为6。在这种情况下,任何一对点都将被一半(一对组)覆盖。并且不要忘记保留所有最小值,而不是在每次递归迭代中保留一个最小值。
此外,由于每次划分集时都必须进行分组,因此会增加复杂度,因此您可能会考虑对小集使用“慢速” O(n²)
算法,因此实际解决方案将是{ {1}}和O(n log n)
。
对于第二个问题,我只能提出避免递归的一般方法。如果您有足够的内存,请使用动态编程,即将以前的所有结果保存在内存中并进行遍历,直到用所有可能的参数填充数组为止。因此,您无需进行递归调用,而只是从数组中获取价值。当然,您必须重新开始,直到数组中没有空值为止。实现因任务而异,因此您必须考虑如何实现这一目标。