Algorithm 直线上给定点的最短距离对?

Algorithm 直线上给定点的最短距离对?,algorithm,computational-geometry,closest-points,Algorithm,Computational Geometry,Closest Points,有人能提出一种算法来找出未排序的共线点的最短距离对吗 我有一个解决方案,它在O(nlogn)中实现这一点,只需执行并应用于行。但是,这能更有效地完成吗?我将针对一个有限范围内的数字列表提出一个解决方案 如果所有的数字都在[a,b]范围内,其中O(b-a)

有人能提出一种算法来找出未排序的共线点的最短距离对吗


我有一个解决方案,它在O(nlogn)中实现这一点,只需执行并应用于行。但是,这能更有效地完成吗?

我将针对一个有限范围内的数字列表提出一个解决方案

如果所有的数字都在[a,b]范围内,其中O(b-a) 创建一个大小为b-a的数组。您可以将其全部初始化为0(在O(1)中有一个算法可以实现这一点)

检查一下你的列表,对于每个值x,将“1”放在单元格的x-a处

然后检查新数组,并计算具有值的单元格之间的距离


这样,您可以找到最小距离,并通过新数组中的索引获得实际值。

恐怕您必须对点进行排序,这至少需要O(n*log(n))时间(除非您可以使用桶排序),因此,我怀疑您是否能找到更快的算法。

请注意,通过执行旋转变换,始终可以将2D情况减少为1D情况

不幸的是,在一般情况下,我不认为你能比O(nlogn)做得更好。您最好的选择是对它们进行排序,然后遍历列表。

这是平面中最近点对的预期O(n)时间算法。
它来自Kleinberg和Tardos的算法设计书

这里是一个类似Python的伪代码

def Bucket(point, buck_size):
  return int(point[0] / buck_size, int(point[1] / buck_size)

def InsertPoint(grid, point, buck_size):
  bucket = Bucket(point, buck_size)
  grid[buck_size].append(point)

def Rehash(points, limit, buck_size):
  grid = collections.defaultdict(list)
  for first limit point in points:
    InsertPoint(grid, point, buck_size)
  return grid

# return new distance if point is closer than buck_size to any point in grid,
# otherwise return inf
def Probe(grid, point, buck_size):
  orig_bucket = Bucket(point)
  for delta_x in [-1, 0, 1]:
    for delta_y in [-1, 0, 1]:
      next_bucket = (orig_bucket[0] + delta_x, orig_bucket[1] + delta_y)
      for cand_point in grid[next_bucket]:  
        # there at most 2 points in any cell, otherwise we rehash 
        # and make smaller cells.
        if distance(cand_point, point) < buck_size):
          return distance(cand_point, point)
  return inf

def ClosestPair(points):
   random_shuffle(points)
   min_dist = distance(points[0], points[1])
   grid = Rehash(points, 2, min_dist)
   for i = 3 to n
     new_dist = Probe(points, i, grid)
     if new_dist != inf:
        # The key to the algorithm is this happens rarely when i is close to n,
        # and it's cheap when i is close to 0.
        grid = Rehash(points, i, new_dist)
        min_dist = new_dist
     else:
        InsertPoint(point, grid, new_dist)
   return min_dist
def桶(点、桶大小):
返回int(点[0]/buck\u size,int(点[1]/buck\u size)
def插入点(网格、点、buck_大小):
桶=桶(点、桶大小)
网格[buck_size]。追加(点)
def再灰化(点数、限制、buck_大小):
grid=collections.defaultdict(列表)
对于点中的第一个极限点:
插入点(网格、点、buck_大小)
回流栅
#如果点距离网格中任何点的距离小于buck_大小,则返回新距离,
#否则返回inf
def探头(网格、点、buck_尺寸):
原始铲斗=铲斗(点)
对于[-1,0,1]中的delta_x:
对于[-1,0,1]中的增量y:
下一个存储桶=(原始存储桶[0]+delta\u x,原始存储桶[1]+delta\u y)
对于网格中的cand_点[下一个桶]:
#任何单元格中最多有2个点,否则我们将重新刷新
#制造更小的细胞。
如果距离(烛光点、点)
每个邻居候选搜索都是O(1),只需进行一些哈希运算。 该算法需要进行O(log(n))重散列,但每一次都需要与i成比例的时间。需要重新灰化的概率为2/i(=该特定点是目前为止最接近的一对的概率是多少?),即该点在检查i点后位于最近的一对中的概率。因此,预期成本为

总和i=2^n概率[第i步再灰化]*成本(第i步再灰化)+O(1)=

和i=2^n2/i*i+O(1)=

和i=2^n2+O(1)=


O(n)

如果(a,b)=(0,1)并且点是0.2和0.3怎么办?这个列表不能保证是整数。很好!但只有当你得到整数时它才起作用。。真的不适合我的情况!!Thanx,兄弟!结果表明,O(nlogn)是最有效的时间复杂度。。顺便说一句,我是这么建议的。谢谢大家的帮助!!!散列,不排序,你可以很容易地击败O(n log n)。排序是足够的,因为没有必要。如果您想找到精确的重复项(而不是接近重复项),您可以使用精确哈希并非常简单地得到一个O(n)算法。你仍然可以玩几何把戏,得到最近对问题的O(n)。我们不想要精确的重复,而是最近点。你的算法方案是什么,适用于O(n)?请你编辑算法,使其更清晰?我被困在第二行(未定义的变量a_1,a_2)。我真的把它充实了起来。但是我仍然没有测试代码。