给定平面上N个点的坐标,找出距离最近的两个点(Java)

给定平面上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坐标排序

扫描二维码关注公众号,回复: 11262895 查看本文章

在这里插入图片描述
图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));
    }

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41718454/article/details/105162089
今日推荐