java最接近對點及距離_最接近點對問題_分治法

一、問題描述

給定平面上的n個點,找其中的一對點,使得在n個點組成的所有點對中該點對間的距離最小。

二、解題思路及所選算法策略的可行性分析

思路:利用分治法來解決問題。遞歸子結構求最接近點對總體可分為幾個步驟:

1、當問題規模小于20,直接求解最小點對

2、將n個點組成的集合S分成2個子集S1和S2

3、遞歸求出兩個子集中的最接近點對并比較出最小點對,記錄距離dmin

4、以X坐標為基準找到所有點中線,在中線附近找出相距可能小于dmin的點對點,記錄于S3和S4

5、求S3和S4每點對距離,和dmin進行比較,求解最接近點對

策略可行性分析:

設直線l上有2m個點,以m為中點將l分割成兩條線段dl,dr,然后求出dl和dr這兩點條線段中的最小點距d1,d2,此時d=min{d1,d2},再通過計算出dl線段的中最大點與dr線段中的最小點之間的距離D,最小距離則為min{d,D}.

二維情況與此相似,最大的區別只是對于中線位置的點,二維情況只是針對中線旁好多可能點,再在Y軸方向上進行點的篩選,以減少平方計算次數。

三、偽代碼描述及復雜度分析

Public static double closestPoint(S)

{

1、首先,遞歸結束條件,當數組長度在一定范圍內時直接求出最近點,蠻力求解

2、求所有點在X坐標中的中位數midX

3、以midX為界將所有點分成兩組分別存放在兩個表中

4、將兩張表轉化為數組類型,并分別按X坐標升序排列

5、求S1中的最近距離的兩個點

6、求S2中的最近距離的兩個點

7、求兩最近距離的最小值

8、在S1、S2中收集距離中線小于d1的點,分別存放于兩個表中

9、分別將表T3、T4轉換為數組類型的S3、S4,并將其分別按Y坐標升序排列

10、求解S3、S4兩者之間可能的更近(相比于d1)距離 , 以及構成該距離的點

}

復雜度分析:

設算法耗時T(n)。 算法第1步、第2步、第3步和第8步用了O(n)時間。第7步和第10步用了常數時間。第4步和第9步用了O(nlogn)時間。第5步和第6步分別用了T(n/2)時間。不過第4步和第9步是數組的排序預處理時間,所以不算在算法中。所以經由預處理的算法所需計算時間滿足遞歸方程:

T(n)={?? O(1)????????? n<4

2T(n/2)+O(n)?? n>=4

由此,T(n)=O(nlogn)。

代碼實現

dcPoint.java

package 分治法;

public class dcPoint implements Cloneable, Comparable{

public dcPoint() {

x = 0;

y = 0;

}

public dcPoint(int x, int y) {

this.x = x;

this.y = y;

}

public void setX(int x) {

this.x = x;

}

public void setY(int y) {

this.y = y;

}

public int getX() {

return x;

}

public int getY() {

return y;

}

private int x;

private int y;

@Override

public int compareTo(dcPoint o) {

if(x == o.getX() && y == o.getY())

return 0;

else

return 1;

}

}

NPointPair.java

package 分治法;

import java.util.ArrayList;

import java.util.Random;

import java.util.Set;

import java.util.TreeSet;

public class NPointPair {

/**

* 最近點問題

* @param S

*/

public static dcPoint[] closestPoint(dcPoint [] S){

dcPoint[] result = new dcPoint[2];

/**

* 0.首先,解決該問題的邊界,當數組長度在一定范圍內時直接求出最近點,蠻力求解

*/

double dmin = Double.POSITIVE_INFINITY;

double tmpmin = 0;

if(S.length <= 20){

for(int i = 0; i < S.length; i ++){

for(int j = i + 1; j < S.length; j ++){

tmpmin = Math.sqrt(Math.pow(S[i].getX() - S[j].getX(), 2)) + Math.pow(S[i].getY() - S[j].getY(), 2);

if(tmpmin < dmin){

dmin = tmpmin;

result[0] = S[i];

result[1] = S[j];

}

}

}

return result;

}

/**

*1.求所有點在X坐標的中位數

*/

int minX = (int) Double.POSITIVE_INFINITY;//保證假設的初始最小值足夠大

int maxX = (int) Double.NEGATIVE_INFINITY;//保證假設的初始最大值足夠小

for(int i = 0; i < S.length; i++){

if(S[i].getX() < minX)

minX = S[i].getX();

if(S[i].getX() > maxX)

maxX = S[i].getX();

}

int midX = (minX + maxX)/2;

/**

* 2.以midX為界將所有點分成兩組分別存放在兩個表中

*/

ArrayList T1 = new ArrayList();

ArrayList T2 = new ArrayList();

for(int i = 0; i < S.length; i++){

if(S[i].getX() <= midX)//是否要=號?

T1.add(S[i]);

if(S[i].getX() > midX)

T2.add(S[i]);

}

/**

* 3.將兩張表轉化為數組類型,并分別按X坐標升序排列

*/

dcPoint [] S1 = new dcPoint[T1.size()];

dcPoint [] S2 = new dcPoint[T2.size()];

T1.toArray(S1);

T2.toArray(S2);

mergeSort(S1, "x");//按X坐標升序排列

mergeSort(S2, "x");//按X坐標升序排列

/**

* 4.求S1中的最近距離的兩個點

*/

dcPoint[] result1 = new dcPoint[2];

result1 = closestPoint(S1);

/**

* 5.求S2中的最近距離的兩個點

*/

dcPoint[] result2 = new dcPoint[2];

result2 = closestPoint(S2);

/**

* 6.求兩最近距離的最小值

*/

double d1 = Math.sqrt(Math.min(Math.pow(result1[0].getX() - result1[1].getX(), 2) + Math.pow(result1[0].getY() - result1[1].getY(), 2),

Math.pow(result2[0].getX() - result2[1].getX(), 2) + Math.pow(result2[0].getY() - result2[1].getY(), 2)));

if(Math.pow(result1[0].getX() - result1[1].getX(), 2) + Math.pow(result1[0].getY() - result1[1].getY(), 2) <

Math.pow(result2[0].getX() - result2[1].getX(), 2) + Math.pow(result2[0].getY() - result2[1].getY(), 2))

result = result1;

else

result = result2;

/**

* 7.在S1、S2中收集距離中線小于d1的點,分別存放于兩個表中

*/

ArrayList T3 = new ArrayList();

ArrayList T4 = new ArrayList();

for(int i = 0; i < S1.length; i++){

if(midX - S1[i].getX() < d1)

T3.add(S1[i]);

}

for(int i = 0; i < S2.length; i++){

if(S2[i].getX() - midX < d1){

T4.add(S2[i]);

}

}

/**

* 8.分別將表T3、T4轉換為數組類型的S3、S4,并將其分別按Y坐標升序排列

*/

dcPoint [] S3 = new dcPoint [T3.size()];

dcPoint [] S4 = new dcPoint [T4.size()];

T3.toArray(S3);

T4.toArray(S4);

mergeSort(S3, "y");

mergeSort(S4, "y");

/**

* 求解S3、S4兩者之間可能的更近(相比于d1)距離 , 以及構成該距離的點

*/

double d = Double.POSITIVE_INFINITY;

for(int i = 0; i < S3.length; i ++){

for(int j = 0; j < S4.length; j ++){

if(Math.abs(S3[i].getY() - S4[j].getY()) < d1){

double tmp = Math.sqrt(Math.pow(S3[i].getX() - S4[j].getX(), 2) + Math.pow(S3[i].getY() - S4[j].getY(), 2));

if(tmp < d){

d = tmp;

result[0] = S3[i];

result[1] = S4[j];

}

}

}

}

return result;

}

//歸并排序

private static void mergeSort(dcPoint[] a, String property){

dcPoint[] tempArray = new dcPoint[a.length];

mergeSort(a, tempArray, 0, a.length - 1, property);

}

private static void mergeSort(dcPoint[] a, dcPoint [] tempArray, int left, int right, String property){

if(left < right){

int center = (left + right) >> 1;

//分治

mergeSort(a, tempArray, left, center, property);

mergeSort(a, tempArray, center + 1, right, property);

//合并

merge(a, tempArray, left, center + 1, right, property);

}

}

private static void merge(dcPoint [] a, dcPoint [] tempArray, int leftPos, int rightPos, int rightEnd, String property){

int leftEnd = rightPos - 1;

int numOfElements = rightEnd - leftPos + 1;

int tmpPos = leftPos;//游標變量, 另兩個游標變量分別是leftPos 和 rightPos

while(leftPos <= leftEnd && rightPos <= rightEnd){

if(property.equals("x")){

if(a[leftPos].getX() <= a[rightPos].getX())

tempArray[tmpPos++] = a[leftPos++];

else

tempArray[tmpPos++] = a[rightPos++];

}else if(property.equals("y")){

if(a[leftPos].getY() <= a[rightPos].getY())

tempArray[tmpPos++] = a[leftPos++];

else

tempArray[tmpPos++] = a[rightPos++];

}else

throw new RuntimeException();

}

while(leftPos <= leftEnd)

tempArray[tmpPos++] = a[leftPos++];

while(rightPos <= rightEnd)

tempArray[tmpPos++] = a[rightPos++];

//將排好序的段落拷貝到原數組中

System.arraycopy(tempArray, rightEnd-numOfElements+1, a, rightEnd-numOfElements+1, numOfElements);

}

public static void main(String[] args) {

Set testData = new TreeSet();

Random random = new Random();

int x = 0;

int y = 0;

for(int i = 0;i < 50;i++){

x = random.nextInt(500);

y = random.nextInt(500);

System.out.println("x:" + x + " y:" + y);

testData.add(new dcPoint(x, y));

}

dcPoint [] S = new dcPoint[testData.size()];

S = (dcPoint[]) testData.toArray(S);

for(int i = 0; i < S.length; i ++){

System.out.println("(" + S[i].getX() + ", " + S[i].getY() + ")");

}

System.out.println(testData.size());

dcPoint [] result = new dcPoint [2];

result = closestPoint(S);

System.out.println("最近的兩點分別是(" + result[0].getX() + ", " + result[0].getY()

+ ") 和 (" + result[1].getX() + ", " + result[1].getY() + "), 最近距離為:"

+ Math.sqrt(Math.pow(result[0].getX() - result[1].getX(), 2) + Math.pow(result[0].getY() - result[1].getY(), 2)));

}

}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/542612.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/542612.shtml
英文地址,請注明出處:http://en.pswp.cn/news/542612.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python return用法_初學Python要了解什么 裝飾器知識匯總有哪些

初學Python要了解什么&#xff1f;裝飾器知識匯總有哪些&#xff1f;在Python學習過程中&#xff0c;有多種方法對函數和類進行加工&#xff0c;相對于其它方式&#xff0c;裝飾器語法簡單&#xff0c;代碼可讀性高。因此&#xff0c;裝飾器在Python項目中有廣泛的應用&#xf…

android emulator虛擬設備分析第三篇之pipe上的qemud service

一、概述 本篇和第二篇是強相關的&#xff0c;需要結合第二篇一起看。 以boot-properties為例&#xff0c;注意不需要看ANDROID-QEMUD.TXT&#xff0c;這個是和guest os中的qemud進行相關的&#xff0c;已廢棄。 啟動emulator時&#xff0c;有一個參數-prop <key><val…

c#異常處理_C#異常處理能力問題和解答 套裝4

c#異常處理1) Which is not a valid keyword used in the context of exception handling? trycatchfinalfinally Answer & Explanation Correct answer: 3final The final keyword is not used to handle exceptions in C#.NET. 1)在異常處理的上下文中使用哪個無效關鍵字…

Castor xsd生成java_java – Castor可以處理從基礎XSD導入的多個XSD生成類嗎?

注意&#xff1a;我是EclipseLink JAXB (MOXy)領導者,也是JAXB 2 (JSR-222)專家組的成員.Can Castor do this? If so, what would be the Ant task syntax for it.If not, would perhaps JAXB be a better alternative?下面是如何使用JAXB完成此操作的示例&#xff1a;產品xm…

串口通信 校驗碼_一文讀懂S7-200 SMART自由口通信!

學習S7-200 SMART時了解到&#xff0c;基于RS485接口可實現一下幾種通信&#xff1a;1&#xff09;modbus RTU通信2&#xff09;PPI協議通信3&#xff09;USS協議通信4&#xff09;自由口通信何為自由口通信呢&#xff1f;前三種通信必須要PLC和與其通信的設備支持相同的通信協…

hbase 學習(十三)集群間備份原理

集群建備份&#xff0c;它是master/slaves結構式的備份&#xff0c;由master推送&#xff0c;這樣更容易跟蹤現在備份到哪里了&#xff0c;況且region server是都有自己的WAL 和HLog日志&#xff0c;它就像mysql的主從備份結構一樣&#xff0c;只有一個日志來跟蹤。一個master集…

python expect模塊_Python基礎教程:用Python怎么telnet到網絡設備

Python基礎教程&#xff1a;用Python怎么telnet到網絡設備0.前言Telnet協議屬于TCP/IP協議族里的一種&#xff0c;對于我們這些網絡攻城獅來說&#xff0c;再熟悉不過了&#xff0c;常用于遠程登陸到網絡設備進行操作&#xff0c;但是&#xff0c;它的缺陷太明顯了&#xff0c;…

Java實現動態加載頁面_[Java教程]動態加載頁面數據的小工具 javascript + jQuery (持續更新)...

[Java教程]動態加載頁面數據的小工具 javascript jQuery (持續更新)0 2014-05-07 18:00:06使用該控件&#xff0c;可以根據url&#xff0c;參數&#xff0c;加載html記錄模板(包含json參數對應&#xff0c;以及具體記錄位置Index根據參數描述加載對應的屬性&#xff0c;并可以…

馬哥linux第六周作業

1、復制/etc/rc.d/rc.sysinit文件至/tmp目錄&#xff0c;將/tmp/rc.sysinit文件中的以至少一個空白字符開頭的行的行首加#&#xff1b;[rootmageedu tmp]# cp /etc/rc.d/rc.sysinit . [rootmageedu tmp]# vim rc.sysinit :% s/^[[:space:]]/#&/ #按Esc進入vi…

Java ObjectInputStream enableResolveObject()方法與示例

ObjectInputStream類enableResolveObject()方法 (ObjectInputStream Class enableResolveObject() method) enableResolveObject() method is available in java.io package. enableResolveObject()方法在java.io包中可用。 enableResolveObject() method is used to enable th…

pygame render怎么顯示中文_PyGame開發游戲(2D)02.基礎圖元

這節將介紹PyGame的基礎架構。并學習如何在PyGame里繪制各種幾何圖形和顯示加載圖片。01.應用框架上一節的示例程序里&#xff0c;我們用到一個PyGame的應用程序框架。這是一個基礎框架&#xff0c;利用它我們可以很輕松的添加各類圖型繪制&#xff0c;鍵盤鼠標輸入處理和各類邏…

word+增加水印+java_為Word2019文檔添加水印的兩種方法

水印的類型包括文字水印和圖片水印兩種。在Word文檔中添加文字水印時&#xff0c;可以使用程序中預設的水印效果&#xff0c;而圖片水印則需要自定義添加。一、使用程序預設的文字水印Word 2019中預設了機密、緊急、免責聲明三種類型的文字水印&#xff0c;用戶可根據文件的類型…

如何設置CentOS 7獲取動態及靜態IP地址

自動獲取動態IP地址1.輸入“ip addr”并按回車鍵確定&#xff0c;發現無法獲取IP(CentOS 7默認沒有ifconfig命令)&#xff0c;記錄下網卡名稱&#xff08;本例中為ens33&#xff09;。2.輸入“cd /etc/sysconfig/network-scripts/”按回車鍵確定&#xff0c;繼續輸入“ls”按回…

請求列出指定服務器上的可用功能失敗_濫用 ESI 詳解(上)

在進行安全性評估時&#xff0c;我們注意到了標記語言 Edge Side Includes (ESI)中的一個意外行為&#xff0c;這種語言用于許多流行的 HTTP 代理(反向代理、負載平衡器、緩存服務器、代理服務器)。我們發現成功的 ESI 攻擊可以導致服務器端請求偽造(SSRF)、各種繞過 HTTPOnly …

Java ClassLoader setPackageAssertionStatus()方法與示例

ClassLoader類setPackageAssertionStatus()方法 (ClassLoader Class setPackageAssertionStatus() method) setPackageAssertionStatus() method is available in java.lang package. setPackageAssertionStatus()方法在java.lang包中可用。 setPackageAssertionStatus() metho…

java上傳kafka的方法_哪種方法是將所有數據從Kafka主題復制到接收器(文件或Hive表)的最佳方法?...

我正在使用Kafka Consumer API將所有數據從Kafka主題復制到Hive表 . 為此&#xff0c;我使用HDFS作為中間步驟 . 我使用唯一的組ID并將偏移重置為“最早”&#xff0c;以便從頭開始獲取所有數據&#xff0c;并在執行后忽略提交 . 然后我遍歷Kafka主題中的記錄&#xff0c;并將每…

openstack nova-network 的小bug的排錯經歷

環境是 nova-network vmwareflatdhcp錯誤表現為 開出來的虛擬機有一定幾率獲取不到dhcp地址&#xff0c;手工賦予ip則正常&#xff0c;用flat模式注入的ip正常&#xff0c;下面是排錯過程1首先找網絡防火墻已經把 dnsmasq對應的端口已經打開抓包結果&#xff1a;可以看到虛擬機…

anaconda base環境_anaconda中安裝packages:pip還是conda install?

conda install我就不說了&#xff0c;這都不會別學了就。Using command:$ which -a pip, the terminal will return:This indicates two different pip path to install packages[1].在tf23環境中pip install在base環境中pip install在windows下powershell內&#xff0c;進入到…

Java ClassLoader setDefaultAssertionStatus()方法與示例

ClassLoader類setDefaultAssertionStatus()方法 (ClassLoader Class setDefaultAssertionStatus() method) setDefaultAssertionStatus() method is available in java.lang package. setDefaultAssertionStatus()方法在java.lang包中可用。 setDefaultAssertionStatus() metho…

【風馬一族_xml】xmlp之dtd1

什么是XML約束&#xff1f;在xml技術里&#xff0c;可以編寫一個文檔來約束一個xml文檔的寫法&#xff0c;這稱之為xml約束 2. 為什么要使用xml約束&#xff1f; 參看提示欄 3. xml約束的作用&#xff1f; 約束xml的寫法對xml進行校驗4. 常見的xml約束技術 xml dtdxml Schema…