給定平面上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座標排序

在這裏插入圖片描述
圖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));
    }

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章