给定平面上N个点的坐标,找出距离最近的两个点(Java)
说实话这道题不太会,以下讲解转自一篇博客,代码转自另一篇(真是太菜了没脸见人了…)
问题:平面点集求其中距离最近的两个点及其距离。
思路:采用分治法,将“求n个点之间最小距离”问题划分为很多个“求n/t个点之间最小距离”问题。
(1)将lstPoint根据X坐标由小到大排序得到点集pointsSortedX,方法很多,冒泡、选择、插入、归并,快排等,本文采用快排,其优点就不多说了。
(2)pointsSortedX为一个点集,可以采用二分法分为两个数量均分的点集pointsX1([0,indexMid]),pointsX2([indexMid,Count-1]),对于每个分点集,求其中距离最近的两个点及其距离,方法如前,采用递归求解;
(3)对于2个分点集,可得两个最小距离,取其小者,为分点集各自内的最小距离dis,但是仍然存在这种情况,即可能存在两个点分别位于两个分点集中,所以还需考虑2个分点集间的情况。而参考已求得的dis,2个分点集间区域可根据X坐标取
X∈[pointsSortedX[indexMid].X - dis,pointsSortedX[indexMid].X + dis]范围的点并构成临时点集pointsTemp;
(4)将点集pointsTemp根据Y坐标进行由小到大排序,对于每个点ptCurrent,求Y坐标∈[ptCurrent.Y - dis, ptCurrent.Y + dis]的点ptCurrent的距离,并与dis取最小赋给dis;
图解如下:
图1 根据X坐标排序
图2 二分法分解
图3 递归求解并考虑区域间点距离最小情况
————————————————
版权声明:本文为CSDN博主「哈市雪花」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/baidu_38621657/article/details/88367170
/*
* @Title divide
* @Description 求平面上距离最近的两个点
* @author 滑技工厂
* @Date 2020/3/28
* @param [left, right, points]
* @return double
* @throws
*/
public static double divide(int left, int right, Point[] points) {
// 当前最小两点距离,初始值设置为无穷大
double curMinDis = 1e20;
// 如果只有一个点,则不存在最近两点距离,返回无穷大
if (left == right) {
return curMinDis;
}
// 这里是判断是否为只有两个点,如果只有两个点的话那么直接求解。
if (left + 1 == right) {
return distance(points[left], points[right]);
}
// 分治法:第一步:分区,并求取左右分区最小两点距离
// 通过右移运算除2,对区域进行合理的划分,使得左右两边保持大致相等个数点
int middle = (left + right) >> 1;
double leftMinDis = divide(left, middle, points);
double rightMinDis = divide(middle, right, points);
curMinDis = (leftMinDis <= rightMinDis) ? leftMinDis : leftMinDis;
// 分治法:第二步:假设距离最近的两点分别在左右分区中
// 关键代码,距离最近的两个点,一个位于左边区域,一个位于右边区域,x轴搜索范围[middle-curMinDis, middle+curMinDis]
// 记录搜索区间内的点的索引,便于进一步计算最小距离
List<Integer> validPointIndex = new ArrayList<>();
for (int i = left; i <= right; i++) {
if (Math.abs(points[middle].x - points[i].x) <= curMinDis) {
validPointIndex.add(i);
}
}
// 基于索引,进一步计算区间内最小两点距离
for (int i = 0; i < validPointIndex.size() - 1; i++) {
for (int j = i + 1; j < validPointIndex.size(); j++) {
// 如果区间内的两点y轴距离大于curMinDis,则没必要计算了,因为,它们的距离肯定大于curMinDis,
if (Math.abs(points[validPointIndex.get(i)].y
- points[validPointIndex.get(j)].y) > curMinDis) {
continue;
}
double tempDis = distance(points[validPointIndex.get(i)],
points[validPointIndex.get(j)]);
curMinDis = (tempDis < curMinDis) ? tempDis : curMinDis;
}
}
return curMinDis;
}
public static double distance(Point p1, Point p2) {
return Math.sqrt((p2.y - p1.y) * (p2.y - p1.y) + (p2.x - p1.x) * (p2.x - p1.x));
}