给定数轴上的n个点,求距离最近的两个点的距离
public class MinimumSpacing {
//给定平面上的n个点,求距离最近的两个点的距离。
//无从下手的话,先分解问题,分解成简单的,逐个分析,然后再合在一起考虑
//这是个2维的数据,那就先降维到1维分析
//先考虑在一条数轴上有n个点,求最近距离的2个点的距离
//
// ------*--*------*---*--->
//用分治思想处理
// 1.分割 2.处理 3.合并 3个步骤
//
// 1.分割:
// 将整个数据[先排序]得到数组s,然后将s从中间一份为二(分割点m下标为, m=(l+r)/2) ,(最小下标+最大下标) / 2,得到左半边s1,和右半边s2
// ------*--*---|---*---*--->
// l m r
// s1 s2
// s
// 当点的个数n有基数个时,左半边为 s1=s[l,m] ,右半边 为 s2=s(m,r]
// 例如n=3 l=0 ,r=2 m=2/2 = 1 ,s1 = 0,1 (2个元素) .s2=2 (1个元素) , s1比s2多一个元素
// n为偶数时候 = 4
// m = 0+3/2 = 1 , s1=0,1 s2=2,3 ,s1和s2元素一样多
//
// 2.处理:
// 用递归的方式处理左右两边,先考虑最小情况
// n = 0 和 n = 1 时
// 返回 -1 ,代表无法判断2个最近的点是哪两个,因为点的个数不足2个
// n = 2 时
// 直接返回 2个点的距离=d
// n = 3 时
// 此时不是最小情况,需要继续切分成2份,分治处理,按照1.分割 的方式去分割
//
// 3.合并:
// 从非最小情况开始考虑(n>=3)
// 因为将s这个数组分割成了2份,每一份会返回该区域的最短距离值(除非不存在,则返回-1,代表该区域只分得0个或1个点,无法判断最小距离)
// ds1 代表 左侧 这一半返回的最小距离
// ds2 代表 右侧 这一半返回的最小距离
// ds 代表当前这个数组应返回的最小距离
// n=3时
// ds
// dsgap (处于分割线两段的点的距离)
// ds1 (ds2:不存在)
// ---*---*|---*--->
// p2 p1 q1
// s1 s2
// s
// 从分治之后的返回值 s1 来看,最短距离的点 只有p1和p2 = d1
// 而s2 的最短距离为 Integer.MAX_VALUE ,因为只有一个点,所以不存在
// 那么可能的情况有
// 1.p1和p2 是最近距离
// 2.还有一个情况从s数组的分割线的角度考虑,s1未处理,s2也未处理的情况:s1 的最右侧点(p1) 和 s2 的最左侧点(q1) 之间的距离 dsgap,dsgap < d1,那么当前数组s中的最小距离ds = dsgap,否则 ds=d1
//
// n=4时
// ds
// dsgap (处于分割线两段的点的距离)
// ds1 ds2
// ---*---*|--*--*--->
// p2 p1 q1 q2
// s1 s2
// s
// 先计算 s1 最大序号顶点p1 和 s2 最小序号顶点 q1 之间的距离 dsgap
// 然后找到 ds1 ,ds2 , dsgap 最小的值,作为当前数组s 的2点最短距离返回值 ds 并返回
//
// 当递归回溯到较高层的时候(n越来越大时)
// n=5.6.7...更多
// ds
// dsgap (处于分割线两段的点的距离)
// ds1 ds2
// ...--*---*--*---*|--*--*---*--*---->...
// p. p3 p2 p1 q1 q2 q3 q4 q.
// s1 s2
// s
// 此时同样需要计算dsgap的值
// 不用知道s1中 ds1 具体是哪2个顶点之间的最小距离,只需知道ds1是左侧不断分治后,直到最小规模情况时返回的整个 s1 的最短距离
// 同理 ds2 也是
// 所以这种情况下找到 s 的 ds 的办法和上面一样
// 1.根据 s1 的最右侧断点 p1 和 s2 最左侧端点 q1 的距离 dsgap
// 2.找到 ds1 和 ds2 和 dsgap 的最短距离作为当前s 的最短距离 ds来返回
//
// 总结一下
// 最小规模下
// n=0,1
// ds1,ds2 无值,dsgap 无值,ds 为 Integer.MAX_VALUE
// n=2
// ds1,ds2 无值,dsgap 无值,ds 为唯一2个点的距离
// n=3,4,5...
// ds1,ds2 可能存在有 Integer.MAX_VALUE 的情况(只分得了1一个点的情况)
// dsgap 有值
// ds = ds1,ds2,dsgap 的最小值 (Integer.MAX_VALUE 的无效值除外)
// 代码:
public static class Point {
int x;
int y;
public Point(int x) {
this.x = x;
}
public Point(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "{" +
"" + x + "," + y +
'}';
}
}
private static void ms1D_Demo() {
//在0~30的范围内,随机生成7个点,并排序
Point[] points = new Point[7];
Random r = new Random("996.251.404.go die".hashCode());
for (int i = 0; i < points.length; i++)
points[i] = new Point(r.nextInt(30));
Arrays.sort(points, new Comparator<Point>() {
@Override
public int compare(Point lhs, Point rhs) {
return lhs.x - rhs.x;
}
});
System.out.println(Arrays.toString(points));
int ds = minimumSpacing1D(points, 0, points.length - 1);
System.out.println(ds);
}
public static int minimumSpacing1D(Point[] points, int l, int r) {
//2.处理:处理最小规模
int len = r - l;
if (len < 1) //1个点 返回无效值
return Integer.MAX_VALUE;
if (len < 2) //2个点 返回这两个点的距离
return points[r].x - points[l].x;
//1.分割:此处对3个点及以上处理
int m = (l + r) >> 1;
int ds1 = minimumSpacing1D(points, l, m); //分治左侧
int ds2 = minimumSpacing1D(points, m + 1, r); //分治右侧
//3.合并:找到当前最短距离是多少
int dsgap = points[m + 1].x - points[m].x; //计算分割线两边的点距
int ds = ds1 < ds2 ? ds1 : ds2;
ds = dsgap < ds ? dsgap : ds; //保留最小点距并返回
return ds;
}
public static void main(String[] ar) {
ms1D_Demo();
}
}
输出
[{0,0}, {5,0}, {8,0}, {9,0}, {17,0}, {21,0}, {25,0}]
1
2维情况
package com.ex.cy.demo4.alg.algthink.divide; import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Random; public class MinimumSpacing { public static class Point {
int x;
int y; public Point(int x) {
this.x = x;
} public Point(int x, int y) {
this.x = x;
this.y = y;
} @Override
public String toString() {
return "{" +
"" + x + "," + y +
'}';
}
} //============
// 考虑2D情况
//============
//代码: public static void ms2d_Demo() {
System.out.println("\n======ms2d_Demo======");
Point[] points = new Point[7];
Random r = new Random("996.251.404.go die".hashCode());
for (int i = 0; i < points.length; i++) {
points[i] = new Point(r.nextInt(40), r.nextInt(40));
} Arrays.sort(points, new Comparator<Point>() {
@Override
public int compare(Point lhs, Point rhs) {
//先按x排序
int dx = lhs.x - rhs.x;
int dy = lhs.y - rhs.y;
if (dx == 0)
return dy; //x值相同,按照y值小的排在数组靠前
return dx; //x值不同,按照x值小的排在数组靠前
}
});
System.out.println(Arrays.toString(points)); float ds = minimumSpacing2D(points, 0, points.length - 1);
System.out.println(ds);
} public static float minimumSpacing2D(Point[] points, int l, int r) {
//2.处理:处理最小规模
int len = r - l;
if (len < 1) //1个点 返回无效值
return Float.POSITIVE_INFINITY;
if (len < 2) { //2个点 返回这两个点的距离
float dst = dst2D(points[r], points[l]);
System.out.println("dst " + dst);
return dst;
} //1.分割:此处对3个点及以上处理
int m = (l + r) >> 1;
float ds1 = minimumSpacing2D(points, l, m); //分治左侧
float ds2 = minimumSpacing2D(points, m + 1, r); //分治右侧
//3.合并:找到当前最短距离是多少
float ds = ds1 < ds2 ? ds1 : ds2; //根据鸽巢原理,另一边用ds画1个 d*2d的矩形,那么在该矩形内不会超过6个点(如果超过的话,根据ds的定义,会产生矛盾)
//也就是说一次合并最多用s2内的,以m为轴,以d为距离,在m的右侧,间隔d的地方画一条平行于m的线 p2
//在p2内任意一点,若存在和[m-ds,m]中有比ds更短距离的匹配,那么不会超过6次匹配
LinkedList<Point> pointXfromMtods = new LinkedList();
for (int i = l; i < r; i++) {
//只对以m:x为中心,+- ds为x范围的点处理,在这个范围内的点,两两比较,试着找到间距小于ds的点对
if (Math.abs(points[i].x - points[m].x) <= ds)
pointXfromMtods.add(points[i]);
}
//按y值升序排序
Collections.sort(pointXfromMtods, new Comparator<Point>() {
@Override
public int compare(Point lhs, Point rhs) {
return lhs.y - rhs.y;
}
});
System.out.println("pointXfromMtods " + pointXfromMtods); for (int i = 0; i < pointXfromMtods.size(); i++) { //找,的x或y 之间距离小于ds的点对
for (int j = i + 1; j < pointXfromMtods.size(); j++) {
int dy = Math.abs(pointXfromMtods.get(j).y - pointXfromMtods.get(i).y);
if (dy > ds)
break; //若发现一个和[i]点的y值 之差 > ds 的,说明已经超出了范围,进入下一个[i]的遍历检测
int dx = Math.abs(pointXfromMtods.get(j).x - pointXfromMtods.get(i).x);
float dsgap = (float) Math.sqrt(dx * dx + dy * dy);
System.out.println("dsgap " + ds);
ds = ds < dsgap ? ds : dsgap;
}
} System.out.println("ds " + ds);
return ds;
} //返回2d空间中 a,b两点的距离
public static float dst2D(Point a, Point b) {
int xx = a.x - b.x;
xx *= xx;
int yy = a.y - b.y;
yy *= yy;
return (float) Math.sqrt(xx + yy);
} public static float dst(int x, int y) {
return (float) Math.sqrt(x * x + y * y);
} public static void main(String[] ar) {
ms2d_Demo();
}
}
[{0,8}, {5,4}, {7,8}, {11,37}, {20,38}, {35,9}, {35,17}]
4.472136
给定数轴上的n个点,求距离最近的两个点的距离的更多相关文章
- Codeforces Round #466 (Div. 2) A. Points on the line[数轴上有n个点,问最少去掉多少个点才能使剩下的点的最大距离为不超过k。]
A. Points on the line time limit per test 1 second memory limit per test 256 megabytes input standar ...
- hdu5795 A Simple Nim 求nim求法,打表找sg值规律 给定n堆石子,每堆有若干石子,两个人轮流操作,每次操作可以选择任意一堆取走任意个石子(不可以为空) 或者选择一堆,把它分成三堆,每堆不为空。求先手必胜,还是后手必胜。
/** 题目:A Simple Nim 链接:http://acm.hdu.edu.cn/showproblem.php?pid=5795 题意:给定n堆石子,每堆有若干石子,两个人轮流操作,每次操作 ...
- GPS(2)关于位置的3个示例,实时获取GPS定位数据,求两个经纬点距离,邻近某个区域圆时警告
实时获取GPS定位数据 import android.app.Activity; import android.content.Context; import android.location.Loc ...
- VB求最大公约数的两个例子
VB求最大公约数的两个算法 Private Sub Command1_Click() Dim a As Long, b As Long a = InputBox("请输入要求最大公约数的整数 ...
- 【Python实践-1】求一元二次方程的两个解
知识点: import sys, sys模块包含了与Python解释器和它的环境有关的函数. “sys”是“system”的缩写.sys.exit() 中途退出程序, (注:0是正常退出,其他为不正常 ...
- scala 求数组排序后每两个元素的差值
求数组排序后每两个元素的差值 例如数组 1,5,8,10,2 求得结果为 1,3,3,2 一般什么样的场景会有这种需求呢? 比如 计算一堆数据在一定时间内的计算时延, 或者得到这段时间内数据的平均计算 ...
- 【Hadoop离线基础总结】MapReduce 社交粉丝数据分析 求出哪些人两两之间有共同好友,及他俩的共同好友都有谁?
MapReduce 社交粉丝数据分析 求出哪些人两两之间有共同好友,及他俩的共同好友都有谁? 用户及好友数据 A:B,C,D,F,E,O B:A,C,E,K C:F,A,D,I D:A,E,F,L E ...
- 数轴上从左到右有n个点a[0],a[1]…,a[n-1],给定一根长度为L的绳子,求绳子最多能覆盖其中的几个点。要求算法复杂度为o(n)。
#include <iostream> using namespace std; int maxCover(int* a, int n, int l) { ; ; ; while(end ...
- 直径上的乱搞 bzoj1999求树直径上的结点+单调队列,bzoj1912负权树求直径+求直径边
直径上的乱搞一般要求出这条直径上的点集或者边集 bzoj1999:对直径上的点集进行操作 /* 给出一颗树,在树的直径上截取长度不超过s的路径 定义点u到s的距离为u到s的最短路径长度 定义s的偏心距 ...
随机推荐
- ansible批量管理常见的配置方法
第7章 ansible的管理 7.1 ansible概念的介绍 ansible-playbook –syntax 检查语法 ansible-playbook -C ...
- 递归的实际业务场景之MySQL 递归查询
喜欢就点个赞呗! 源码<--请点击此处查看 引入 当我看到一些评论时,例如下面的样子.我挺好奇这个功能是怎么样做出来的.进过查阅资料,发现这其实是 MySQL 的递归操作.下面就让我操作一下怎么 ...
- 【Java Web开发学习】Spring MVC整合WebSocket通信
Spring MVC整合WebSocket通信 目录 ========================================================================= ...
- django----session相关配置
1. 数据库Session SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认) 2. 缓存Session SESSION_E ...
- 在 Windows 10 上搭建 Cordova 跨平台开发 Android 环境
目录 安装 Cordova 安装 Java 和 Android 环境 创建 Cordova 应用程序 构建和运行 Cordova Cordova 简介:Cordova 原名 PhoneGap,是一个开 ...
- elasticsearch的快速安装
在阿里云服务器快速安装ElasticSearch 1.安装好java的jdk环境 2.使用wget下载elasticsearch安装包,wget的速度比较满,如果等不及的话,可以先下载好安装包再上传解 ...
- mysql重点中的重点---->查询中的关键字优先级
1.from 找到表 2.where 拿着where指定的约束条件,去文件/表中取出一条条记录 3.group by 将取出的一条条记录进行分组group by ,如果没有group by ,则整体作 ...
- 骚年,如果你还不懂一些java常识?中了奖也无法兑换
今天下午约着几个朋友一起去看叶问4,结果碰到了一个有趣的事情,正好和java有关所以写一篇文章来记录一下. 事件:我和朋友小李.小王一起去看电影 时间:2019/12/21 地点:H市某家电影院 起因 ...
- 张亦总结《AG百家乐庄闲,龙虎中下三路技巧和三株路的运用》
关于三珠路的各种打法,这里我做个详细的讲解 三珠路的打法源于澳门赌王叶汉,需要了解赌王叶汉的著作<BJL投注公式>的可以加我Q:<10353581>进行详细解答 叶汉的打法 ...
- [ASP.NET Core 3框架揭秘] 依赖注入[10]:与第三方依赖注入框架的适配
.NET Core具有一个承载(Hosting)系统,承载需要在后台长时间运行的服务,一个ASP.NET Core应用仅仅是该系统承载的一种服务而已.承载系统总是采用依赖注入的方式来消费它在服务承载过 ...