分治法在求解“最近对”问题中的应用(JAVA)

分治法在求解“最近对”问题中的应用

最近对问题在蛮力法中有过讲解,时间复杂度为O(n^2),下面将会采用分治法讲解这类问题,时间复杂度会降到O(nlogn)

我们将笛卡尔平面上n>1个点构成的集合称为P。若2<= n <= 3时,我们1可以通过蛮力法求解。但当n>3时,采用分治法或许是个更好的选择。假设这些点是按照x轴、y轴升序排列的,可以找出点集在x轴方向上的中位数m,做一条垂直x轴的分割线,由此点将点集划分为左右两个大小为n/2的子集P1和P2,之后通过递归求解出在子集中的最近对距离d1,d2,最后找出d=max{d1,d2}。

但是!!!不巧的是,我们忽略了一个问题,如果距离最近的两个点刚好分别在两个子集中,那么d就不是所有点对的最小距离。我们需要在每次合并子问题结果时,要加以判断是否存在这样的点对。方法是:只考虑以分割线为对称轴、宽度为2d的垂直带中的的点,因为其他点对的距离都是大于d的。

这里给出一个优化,当我们在垂直带中找到一个点p,只需要考虑p之后的5个点即可。

这是因为:如果我们在垂直带中找到p-p'两点的距离小于p,由于我们的序列时经过排序的,所以p'一定在p之后,且两点在y轴上的距离一定是小于d的(根据勾股定理,两点之间的距离如果小于d,那么x轴分量和y轴分量都是小于d的,反之,不可能存在这个点)。所以在几何学上,p'的位置一定在下图中的淡黄色矩形区域。而矩形区域内一般只能包含少量的候选点,这个数量最大为6(根据鸽巢定理)。图中6个红色点为极端的临界情况。我们将d * 2d的矩形划分为d/2 * 2d/3的6块区域,如果超过6个点,假设为7,那么一定会出现某个小矩形中有两个点,这两个点的最大距离为图中红线距离5/6d <d,这和d的意义不符。


import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;class Point {double x;double y;Point (double x, double y) {this.x = x;this.y = y;}
}
public class Main {static Point[] point;static Point[] minP = new Point[2];static Scanner in = new Scanner(System.in);public static void main(String[] args) {int n = in.nextInt();point = new Point[n];
//        for (int i = 0; i < n; i++) {
//            int a = in.nextInt();
//            int b = in.nextInt();
//            point[i] = new Point(a, b);
//        }point[0] = new Point(1,3);point[1] = new Point(2,1);point[2] = new Point(3,5);point[3] = new Point(4,4);point[4] = new Point(5,2);Arrays.sort(point,0, n, new Comparator<Point>() {@Overridepublic int compare(Point o1, Point o2) {return (int) (o1.x - o2.x);}});System.out.println(point.length);double minD = closestPoint(0, point.length-1);for (int i = 0; i < 2; i++) {System.out.println(minP[i].x + "," + minP[i].y);}System.out.println(minD);}private static double closestPoint(int low, int high) {Point[] temp1 = new Point[2];Point[] temp2 = new Point[2];Point[] p = new Point[high - low + 1];double d, d1, d2, d3;int index = 0;if (high - low == 1) {minP[0] = new Point(point[low].x, point[low].y);minP[1] = new Point(point[high].x, point[high].y);return distance(point[low], point[high]);}if (high - low == 2) {d1 = distance(point[low], point[low+1]);d2 = distance(point[low+1], point[high]);d3 = distance(point[low], point[high]);if ((d1 <= d2) && (d1 <= d3)) {minP[0] = new Point(point[low].x, point[low].y);minP[1] = new Point(point[low+1].x, point[low+1].y);return d1;} else if (d2 <= d3) {minP[0] = new Point(point[low+1].x, point[low+1].y);minP[1] = new Point(point[high].x, point[high].y);return d2;} else {minP[0] = new Point(point[low].x, point[low].y);minP[1] = new Point(point[high].x, point[high].y);return d3;}}int mid = (low + high) / 2;d1 = closestPoint(low, mid);temp1[0] = minP[0];temp1[1] = minP[1];d2 = closestPoint(mid+ 1, high);temp2[0] = minP[0];temp2[1] = minP[1];if (d1 < d2) {d = d1;minP[0] = temp1[0];minP[1] = temp1[1];} else {d = d2;minP[0] = temp2[0];minP[1] = temp2[1];}for (int i = mid;i>=low && (point[mid].x - point[i].x) < d; i--) {p[index++] = point[i];}for (int i = mid+1;i<=high && (point[i].x - point[mid].x) < d; i++) {p[index++] = point[i];}Arrays.sort(p, 0, index, new Comparator<Point>() {@Overridepublic int compare(Point o1, Point o2) {return (int) (o1.y - o2.y);}});for (int i = 0; i < index-1; i++) {for (int j = i+1; j < index; j++) {if ((p[j].y - p[i].y) >= d) {break;} else {d3 = distance(p[i], p[j]);if (d3 < d) {minP[0] = new Point(p[i].x, p[i].y);minP[1] = new Point(p[j].x, p[j].y);}}}}return d;}private static double distance(Point p1, Point p2) {return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));}
}

Input:

5

Output:

4.0,4.0
3.0,5.0
1.4142135623730951

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/569761.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转】python的复制,深拷贝和浅拷贝的区别

在python中&#xff0c;对象赋值实际上是对象的引用。当创建一个对象&#xff0c;然后把它赋给另一个变量的时候&#xff0c;python并没有拷贝这个对象&#xff0c;而只是拷贝了这个对象的引用 一般有三种方法&#xff0c; alist[1,2,3,["a","b"]] &#x…

分治法在求解凸包问题中的应用(JAVA)--快包算法

分治法在求解凸包问题中的应用&#xff08;JAVA&#xff09; 之前写过一篇蛮力法在求解凸包问题中的应用&#xff08;JAVA&#xff09;还算简单易懂&#xff0c;没有基础的读者最好先去阅读以下。这里用分治法来求解凸包问题&#xff0c;由于这个算法和快速排序十分相似&#x…

动态规划在求解硬币问题中的应用(JAVA)--币制最大化、找零问题、硬币收集问题

动态规划&#xff1a;这种算法思想多用来求解最优化问题&#xff0c;因此这里存在一个最优化法则&#xff0c;法则指出最优化问题任一实例的最优解&#xff0c;都是由其子实例的最优解构成的。一般来说&#xff0c;自底向上的动态规划更容易设计&#xff0c;但是带有记忆功能的…

使用网络TCP搭建一个简单文件下载器

说明&#xff1a;该篇博客是博主一字一码编写的&#xff0c;实属不易&#xff0c;请尊重原创&#xff0c;谢谢大家&#xff01; 目录 一丶项目介绍 二丶服务器Server 三丶测试TCP server服务器 四丶客户端Client 五丶测试客户端向服务器下载文件 一丶项目介绍 1.叙述 生活中大家…

动态规划在求解背包问题中的应用(JAVA)--回溯法、记忆化法

动态规划在求解背包问题中的应用 背包问题向来是动态规划的典型问题&#xff0c;给定n个重量为w1,w2,...,wn&#xff0c;价值为v1,v2,...,vn的物品和一个称重量为W的背包&#xff0c;求这些物品中最优价值的一个子集&#xff0c;且能够装到背包中。 之前用蛮力法做过背包问题蛮…

JS跨域问题

因为浏览器的同源策略&#xff0c;默认情况下&#xff0c;JavaScript在发送AJAX请求时&#xff0c;URL的域名必须和当前页面完全一致。 完全一致的意思是&#xff0c;域名要相同&#xff08;www.example.com和example.com不同&#xff09;&#xff0c;协议要相同&#xff08;ht…

svn 服务器的搭建以及客户端的使用

1、svn 服务器的搭建以及客户端的使用&#xff0c;安装见下面的博客 https://blog.csdn.net/zh123456zh789/article/details/80921179 说明&#xff1a;服务器只是用来存储数据&#xff0c;服务器上的数据可以通过客户端torisesvn进行操作。比如将自己的项目存到服务器&#xf…

动态规划在求解传递闭包问题中的应用(JAVA)--Warshell算法

动态规划在求解传递闭包问题中的应用&#xff1a; 传递闭包&#xff1a;对于n个顶点有向图来说&#xff0c;如果第i个顶点到第j个顶点之间存在一条有效的有向路径&#xff08;即长度大于0的路径&#xff09;&#xff0c;那么T(i, j) 1,否则T(i, j) 0。例如&#xff1a;求解传…

Centos 7 LVM xfs文件系统修复

情况1&#xff1a; [sda] Assuming drive cache: write through Internal error xfs XFS_WANT_CORRUPTED_GOTO at line 1662 of file fs/xfs/libxfs/xfs_alloc.c Caller xfs_free_extent0x130 [xfs] Internal error xfs_trans_cancel at line 990 of file fs/xfs/xfs_trans.c.C…

动态规划在求解全源最短路径中的应用(JAVA)--Floyd算法

参考图论算法&#xff08;二&#xff09;-最短路径的Dijkstra [ 单源 ] 和Floyd[ 多源 ] 解法&#xff08;JAVA &#xff09;这种算法也叫Floyd-Warshell算法&#xff0c;虽然和Warshell算法名字相近&#xff0c;算法思想也相近&#xff0c;但确实是两种算法。对于一个带权图&a…

录播图的分页使用进度条形式显示

本次我是使用的slick轮播图插件&#xff0c;其官网网址如下&#xff1a; http://kenwheeler.github.io/slick/&#xff0c;下面是轮播图中的代码&#xff0c;如果你不知道效果是什么样子&#xff0c;亦可以去看一下阿里云的官网&#xff1a;https://www.aliyun.com/?utm_conte…

贪婪算法在求解最小生成树中的应用(JAVA)--Prim算法

贪婪算法&#xff1a;通过一系列步骤来构造问题的解&#xff0c;每一步对目前构造的部分分解做一个拓展&#xff0c;直到获得问题的完整解为止,而算法的核心思想就在于&#xff0c;算法的每一步都必须满足以下条件&#xff1a;可行&#xff08;满足问题的约束条件&#xff09;、…

贪婪算法在求解最小生成树中的应用(JAVA)--Kruskal算法

Kruskal算法又被称为“加边法”&#xff0c;这种算法会将加权连通图的最小生成树看成具有V-1条边的无环子图&#xff0c;且边的权重和最小。算法开始时&#xff0c;会按照权重的非递减顺序对图中的边排序&#xff0c;之后迭代的以贪婪的方式添加边。 下面以下图为例来讲解Krusk…

贪婪算法在求解最短路径中的应用(JAVA)--Dijkstra算法

最短路径问题最经典的算法就是Dijkstra算法&#xff0c;虽然不如Floyd算法能够求全源的最短路径&#xff0c;但是在效率上明显强于Floyd算法。 想了解Floyd算法的读者可以参考动态规划在求解全源最短路径中的应用&#xff08;JAVA&#xff09;--Floyd算法 单源最短路径问题是对…

贪婪算法在解决哈夫曼树及编码问题中的应用

哈夫曼编码&#xff0c;是一种可变字长编码(VLC)的高效算法。该算法是Huffman于1952年提出一种编码方法&#xff0c;该方法完全依据字符出现概率来构造异字头的平均长度最短的码字&#xff0c;有时称之为最佳编码。 相比定长编码来说&#xff0c;这种编码实现的压缩率&#xff…

素数筛法求十亿内所有质数的和(C++)

埃拉托斯特尼筛法&#xff08;又称埃氏筛&#xff09;的基本思想是&#xff1a;要得到自然数n以内的全部素数&#xff0c;必须把不大于的所有素数的倍数剔除&#xff0c;剩下的就是素数。 时间复杂度O(nloglogn) #include <iostream> #include <math.h> using na…

spring事务的传播机制新解

以下是事物的传播机制&#xff1a; Transactional(propagationPropagation.REQUIRED)如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)Transactional(propagationPropagation.NOT_SUPPORTED)容器不为这个方法开启事务Transactional(propagationPropagation.REQUIRES_NE…

时空权衡在模式匹配算法中的应用(JAVA)--Horspool算法(简化版BM算法)

模式匹配是数据结构中字符串的一种基本运算&#xff0c;给定一个子串&#xff0c;要求在某个字符串中找出与该子串相同的所有子串。假设P是给定的子串&#xff0c;T是待查找的字符串&#xff0c;要求从T中找出与P相同的所有子串&#xff0c;这个问题成为模式匹配问题。P称为模式…

从wireshake分析http和https的通信过程

参考文章: Wireshark基本介绍和学习TCP三次握手【技术流】Wireshark对HTTPS数据的解密Wireshark/HTTPSJourney to HTTP/2以TCP/IP协议为例&#xff0c;如何通过wireshark抓包分析&#xff1f;TCP三次握手和四次挥手Https详解wireshark抓包演示前言 面试被问到有没有用过抓包工具…

Java对象的序列化和反序列化

原文&#xff1a;https://www.cnblogs.com/xdp-gacl/p/3777987.html 一、序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化。  把字节序列恢复为对象的过程称为对象的反序列化。 对象的序列化主要有两种用途&#xff1a; 1&#xff09; 把对象的字节序列永…