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.mzph.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…