用分治法解决最近对问题

1.问题描述
给出在同一个平面内所有点的坐标,然后找出这些点中最近的两个点的距离。
2.解析
将所给平面上n个点的集合S分成两个子集S1和S2,每个子集中约有n/2个点。然后在每个子集中递归地求最接近的点对。在这里,一个关键的问题是如何实现分治法中的合并步骤,即由S1和S2的最接近点对,如何求得原集合S中的最接近点对。如果这两个点分别在S1和S2中,问题就变得复杂了。

为了使问题变得简单,首先考虑一维的情形。此时,S中的n个点退化为x轴上的n个实数x1,x2,…,xn。最接近点对即为这n个实数中相差最小的两个实数。显然可以先将点排好序,然后线性扫描就可以了。但我们为了便于推广到二维的情形,尝试用分治法解决这个问题。

假设我们用m点将S分为S1和S2两个集合,这样一来,对于所有的p(S1中的点)和q(S2中的点),有p<q。递归地在S1和S2上找出其最接近点对{p1,p2}和{q1,q2},并设d = min{ |p1-p2| , |q1-q2| } 由此易知,S中最接近点对或者{p1,p2},或者是{q1,q2},或者是某个{q3,p3},如下图所示。
在这里插入图片描述
如果最接近点对是{q3,p3},即|p3-q3|<d,则p3和q3两者与m的距离都不超过d,且在区间(m-d,d]和(d,m+d]各有且仅有一个点。这样,就可以在线性时间内实现合并。

此时,一维情形下的最近点对时间复杂度为O(nlogn)。
在二维的情况下:

我们仿照一维的情况先把所有点按照x(横坐标)从左到右升序排列.
在这里插入图片描述
以X横坐标中间的点作为分界线.将平面的点分成左边和右边,以上图为例,分为左边5个右边5个.

然后找到左边的点中最近点对的距离d1,和右边最近点对的距离d2。

令d=min{d1,d2}.那么d是当前整个平面的最近点对的距离吗?
答案不是!!
当前的d1,d2都是两边各自的点的最近距离,但是没有考虑到两边的点相互配对的情况,即是点对一个在左边区域,一个在右边区域。如果我们这个时候把两边相互配对的所有情况全部罗列出来那么时间复杂度就变为第一种方法的O(n2).这个时候我们便可以用上面找到的d来限制配对.即是明显超过d的两点不需要配对.如下:
在这里插入图片描述
那么在范围内的只有三个点,也就是说只有这个三个点相互配对的距离才可能比d小.那么再按照方法一一样在这些点中找到最短距离再跟d去比较.小的就是当前整个平面中所考虑的所有点中最近点对的距离。

然而在以上问题处理上,有一个问题尚未解决就是如何找到两边区域中的最近点对的距离d1,d2 。

我们可以发现在处理上面这个问题的时候,和最开始处理所有平面的点最近点距离的问题类似,只是点的数目减半了.

那么我们可以递归以上问题.直到划分的区域中只有一个或者两个点.这样,该区域的最近点对距离就是无穷大或者该两点的距离。这也是递归终止的条件。
3.设计

double Closest_Pair(int left, int right){
   
    double d = inf;
     if (left == right)
         return d;
     if (left + 1 == right)
         return dis(left, right);
     int mid = (left + right) >> 1;
     double d1 = Closest_Pair(left, mid);
     double d2 = Closest_Pair(mid + 1, right);
     d = min(d1, d2);
     int i, j, k = 0;
     //分离出宽度为d的区间  
     for (i = left
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值