分治法--最邻近点对问题

问题定义:

输入:空间上n个点的集合Q

输出:最近点的距离

定义

Dis(X,Y)为点X和点Y之间的距离

Cross(Q1,Q2)为横跨Q1和Q2两个点集的最小距离

【一维】

思路:

1. 划分:将数轴上的点用中位数m分成两个集合

2. 求解:递归在Q1和Q2中求解子问题

3. 合并:MIN(Q)= min(MIN(Q1),MIN(Q2),Cross(Q1,Q2))

时间复杂度分析:

划分:O(n);求解:2T(n/2);合并:O(1);

T(n)= 2T(n/2)+O(n)=O(nlogn)

 伪代码:

//参数A:点的数组(已经按坐标排列)

//参数low:最左边的点下标

//参数high:最右边点下标

Find_MinDis(A,low,high)

        if(high-low == 1)   return Dis(A[low],A[high]);

        else if(high - low > 1)

                  mid = (low+high)/2

                  Left_min = Find_MinDis(A,low,mid)

                  Right_min=Find_MinDis(A,mid+1,high)

                  Cross_min=Dis(A[mid],A[mid+1])

        return Min(Left_min,Right_min,Cross_min);

【二维】  

思路:

划分:  将点按照横坐标的中位数划分成两部分

记S1和S2中的最小距离d1和d2,设d=min(d1,d2)。

求解:分别递归的计算出S1和S2的最小距离

合并:MIN(S)= min(MIN(S1),MIN(S2),Cross(S1,S2))

问题在于:如何找到横跨S1和S2的两点最小距离

若使用暴力搜索 ,理论上需要进行n^2/4次计算

下面使用方法来缩小寻找点的范围:

1. 容易得知:对S1的任意一个点p来说,满足条件的点一定落在S2中d*2d的范围内

2. 进一步缩小范围,S2中任意两点距离大于等于d,由抽屉原理得知,任意两点不在同一个小矩形中

即只需考虑最多6个点

3. 这样就将时间缩减到6*n/2=3n,即O(n),总的时间复杂度依然是O(nlogn)

原文地址:https://www.cnblogs.com/duanshuai/p/13163018.html