题目
Given a set S of n points in the plane (n is power of 2), c1=(x1, y1), c2=(x2, y2), …, cn=(xn, yn), where the points are ordered in ascending order of their x coordinates, find a pair points with closed instance.
给出一组点c1=(x1, y1), c2=(x2, y2), …, cn=(xn, yn),找出他们之间距离最近的两个点,其中点ci的坐标xi按升序排列。
解题思路
对与这个问题,显然无脑解法是将S中每个点做两两对比,复杂度为O(n^2)。所以现在的目标是降低复杂度。
1.尝试使用分治法将问题缩小化
以x=c为界将点集S分为S1,S2。
2.尝试使用递归解决问题
目前距离最小的点p1,p2只可能有三种分布情况。
p1,p2都在S1中
p1,p2都在S2中
p1,p2分别在S1,S2中
于是问题简化变成了在S1,S2区域里寻找最短的距离d1,d2,寻找相邻区域中最短的距离d3。这里可以观察到,问题变小了。我们将点集S缩小为了S1,S2。这个问题可以应用递归来解决。
所以现在假设d1,d2 是可以求得的(别问,问就是要相信递归),那么问题简化为 已知d1,d2 求d3。
此时如果将S1中的所有点与S2中的所有点做两两比较,时间复杂度和题头写的无脑解法没区别了。那么现在的问题简化为想个方法减少计算的点的数目。
令d=min(d1,d2) 可以观察到只有距离x=c小于d的点之间的距离才可能小于d。只需取(c-d,x+d)之间的点进行计算。同理对于p(x1,y1)∈S1,q(x2,y2)∈S2。只需取|y2-y1|小于d的点进行计算。即只需计算在d x 2d范围内的点。
计算出d3的值后,S中点的最短距离为d=min(d3,d1,d2)
3.复杂度分析
证明d x 2d中最多只能有6个点:1
2将d x 2d分为六块等大矩形,每块矩形大小为d/2 x 2d/3 在每块矩形中斜边距离为5d/6 < d。
即每块矩形中最多只能存在一个点。
复杂度为: 6 x n/2 = 3n
可得出T(n)的表达式:
即:总时间复杂度为:T(n)=O(nlogn)
4.伪代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26getClosestPairDistances(S){
n=S.lenth();
if (n < 2) return flag;
/*Use x=c to construct S1 and S2, where c is the median of all x coordinates in S*/;
S1={p∈S|x(p)<=c},
S2={q∈S|x(q)>c};
d1=getClosestPairDistances(S1);
d2=getClosestPairDistances(S2);
if(d1=flag&&d2=flag){
return getDistance(p,q);
}
else if(d1=flag&&d2!=flag){d1=d2}
else if(d2=flag&&d1!=flag){d2=d1}
d=min(d1,d2);
for(p : S1){
if(x(p)-c<=d){
for(q : S2){
if(|y(q)-y(p)|<=d){
if(getdistance(p,q)<d)d=getdistance(p,q);
}
}
}
}
return d;
}
Java解决
1 | import java.awt.Point; |
C++解决
1 | 任性不想写了 |