【分治】最接近点对Python实现

文章目录

    • @[toc]
      • 问题描述
      • 一维最接近点对算法
        • `Python`实现
      • 二维最接近点对算法
        • 分治算法
        • 时间复杂性
        • `Python`实现

问题描述

  • 给定平面上 n n n个点,找其中的一对点,使得在 n n n个点组成的所有点对中,该点对的距离最小

一维最接近点对算法

Python实现
import sysdef closest_pair(points):points.sort()  # 按照横坐标排序min_dist = sys.maxsize  # 初始化最小距离为一个很大的数closest = None  # 初始化最接近点对为 Nonefor i in range(len(points) - 1):dist = abs(points[i] - points[i + 1])  # 计算相邻点对的距离if dist < min_dist:min_dist = distclosest = (points[i], points[i + 1])return closestpoints = [2, 4, 1, 5, 8, 9, 3]res = closest_pair(points)print(f'最接近的点对: {res}')

二维最接近点对算法

分治算法
  • 选取一垂直线 l : x = m l : x = m l:x=m m m m S S S中各点 x x x坐标的中位数,将 S S S分割为 S 1 = { p ∈ S ∣ x ( p ) ≤ m } S_{1} = \set{p \in S \mid x(p) \leq m} S1={pSx(p)m} S 2 = { p ∈ S ∣ x ( p ) > m } S_{2} = \set{p \in S \mid x(p) > m} S2={pSx(p)>m}
  • 递归地在 S 1 S_{1} S1 S 2 S_{2} S2上解最接近点对问题,分别得到 S 1 S_{1} S1 S 2 S_{2} S2中的最小距离 d 1 d_{1} d1 d 2 d_{2} d2
  • d = min ⁡ { d 1 , d 2 } d = \min\set{d_{1} , d_{2}} d=min{d1,d2},若 S S S的最接近点对 ( p , q ) (p , q) (p,q)之间的距离小于 d d d,则 p p p q q q必分属于 S 1 S_{1} S1 S 2 S_{2} S2,设 p ∈ S 1 p \in S_{1} pS1 q ∈ S 2 q \in S_{2} qS2,则 p p p q q q距直线 l l l的距离均小于 d d d
  • P 1 P_{1} P1 P 2 P_{2} P2分别表示直线 l l l的左侧和右侧宽为 d d d的两个垂直长条区域,则 p ∈ P 1 p \in P_{1} pP1 q ∈ P 2 q \in P_{2} qP2,此时 P 1 P_{1} P1中所有点与 P 2 P_{2} P2中所有点构成的点对均为最接近点对的候选者,在最坏情况下有 n 2 / 4 n^{2} / 4 n2/4对这样的候选者,但是对于 P 1 P_{1} P1中任一点 p p p P 2 P_{2} P2中最多只有 6 6 6个点与它构成最接近点对的候选者
    • 实际上对于 P 1 P_{1} P1中任一点 p p p,若与 P 2 P_{2} P2中的点构成最接近点对的候选者,则必有 d i s t a n c e ( p , q ) < d distance(p , q) < d distance(p,q)<d,满足这个条件的 P 2 P_{2} P2中的点一定落在一个 d × 2 d d \times 2d d×2d的矩形 R R R
    • 可将矩形 R R R的长为 2 d 2d 2d的边 3 3 3等分,将长为 d d d的边 2 2 2等分,由此导出 6 6 6 ( d / 2 ) × ( 2 d / 3 ) (d / 2) \times (2d / 3) (d/2)×(2d/3)的矩形,矩形 R R R中最多只有 6 6 6 S S S中的点

1

  • 合并步骤中,最多只需检查 6 × n / 2 = 3 n 6 \times n / 2 = 3n 6×n/2=3n个候选者,为了确切地知道要检查哪 6 6 6个点,将 p p p P 2 P_{2} P2中的点投影到垂直线 l l l上,能与 p p p点一起构成最接近点对候选者的 q q q p p p l l l上投影点的距离小于 d d d,且这种投影点最多只有 6 6 6个,若将 P 1 P_{1} P1 P 2 P_{2} P2中所有 S S S中点按其 y y y坐标排好序,则对 P 1 P_{1} P1中所有点,对排好序的点列做一次扫描,就可以找出所有最接近点对的候选者
时间复杂性

T ( n ) = { O ( 1 ) , n < 4 2 T ( n / 2 ) + O ( n ) , n ≥ 4 T(n) = \begin{cases} O(1) , & n < 4 \\ 2 T(n / 2) + O(n) , & n \geq 4 \end{cases} T(n)={O(1),2T(n/2)+O(n),n<4n4

T ( n ) = O ( n log ⁡ n ) T(n) = O(n \log{n}) T(n)=O(nlogn)

Python实现
import math# 计算两点之间的欧几里德距离
def dist(p1, p2):return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)# 分治法求解最接近点对问题
def closest_pair(points):# 如果点集中的点个数小于等于 3 个, 直接计算并返回最小距离对if len(points) <= 3:min_dist = float('inf')min_pair = Nonefor i in range(len(points)):for j in range(i + 1, len(points)):d = dist(points[i], points[j])if d < min_dist:min_dist = dmin_pair = (points[i], points[j])return min_pair# 将点集按照 x 坐标排序sorted_points = sorted(points, key=lambda p: p[0])# 将点集分成左右两部分mid = len(sorted_points) // 2left_points = sorted_points[:mid]right_points = sorted_points[mid:]# 递归求解左右两部分的最接近点对left_min_pair = closest_pair(left_points)right_min_pair = closest_pair(right_points)# 取左右两部分最接近点对的最小距离if left_min_pair is None:min_dist = dist(right_min_pair[0], right_min_pair[1])min_pair = right_min_pairelif right_min_pair is None:min_dist = dist(left_min_pair[0], left_min_pair[1])min_pair = left_min_pairelse:left_dist = dist(left_min_pair[0], left_min_pair[1])right_dist = dist(right_min_pair[0], right_min_pair[1])if left_dist <= right_dist:min_dist = left_distmin_pair = left_min_pairelse:min_dist = right_distmin_pair = right_min_pair# 在横跨左右两部分的点中寻找更近的点对mid_x = sorted_points[mid][0]strip = []# 将点集按照 y 坐标排序sorted_points = sorted(points, key=lambda p: p[1])for point in sorted_points:if abs(point[0] - mid_x) < min_dist:strip.append(point)for i in range(len(strip)):for j in range(i + 1, min(i + 7, len(strip))):d = dist(strip[i], strip[j])if d < min_dist:min_dist = dmin_pair = (strip[i], strip[j])return min_dist, min_pairpoints = [(2, 3), (12, 30), (40, 50), (5, 1), (12, 10), (3, 4)]min_dist, min_pair = closest_pair(points)print(f'最接近的点对为: {min_pair}, 点对距离为 {min_dist}')

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

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

相关文章

LED透镜粘接UV胶是一种特殊的UV固化胶,用于固定和粘合LED透镜。

LED透镜粘接UV胶是一种特殊的UV固化胶&#xff0c;用于固定和粘合LED透镜。 它具有以下特点&#xff1a; 1. 高透明度&#xff1a;LED透镜粘接UV胶具有高透明度&#xff0c;可以确保光线的透过性&#xff0c;不影响LED的亮度和效果。 2. 快速固化&#xff1a;经过UV紫外线照射…

CPU、MCU、MPU、DSP、FPGA各是什么?有什么区别?

1、CPU 中央处理器&#xff0c;简称 CPU&#xff08;Central Processing Unit&#xff09;&#xff0c;中央处理器主要包括两个部分&#xff0c;即控制器、运算器&#xff0c;其中还包括高速缓冲存储器及实现它们之间联系的数据、控制的总线。 电子计算机三大核心部件就是CPU…

力扣257. 二叉树的所有路径(递归回溯与迭代)

题目&#xff1a; 给你一个二叉树的根节点 root &#xff0c;按 任意顺序 &#xff0c;返回所有从根节点到叶子节点的路径。 叶子节点 是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [1,2,3,null,5] 输出&#xff1a;["1->2->5","…

[陇剑杯 2021]简单日志分析

[陇剑杯 2021]简单日志分析 题目做法及思路解析&#xff08;个人分享&#xff09; 问一&#xff1a;某应用程序被攻击&#xff0c;请分析日志后作答&#xff1a; 黑客攻击的参数是______。&#xff08;如有字母请全部使用小写&#xff09;。 题目思路&#xff1a; 分析…

C++牛客知识点2

提示&#xff1a;接上文 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;随着人工智能的不断发展&#xff0c;机器学习这门技术也越来越重要&#xff0…

http与https的区别,以及生产环境配置https的几种方式

http HTTP(超文本传输协议)是一种用于传输和处理超文本文档的协议。HTTP使用客户端-服务器模型。客户端通过HTTP请求协议向服务器发送请求&#xff0c;服务器则使用HTTP响应协议返回响应。HTTP协议通常使用TCP/IP作为底层传输协议&#xff0c;但它也可以使用其他传输协议。 H…

sql注入学习

基础查询语句&#xff1a; 给指定字段添加数据 insert into 表名(字段名1,字段名2,.....) values(值1,值2,......); 给全部字段添加数据 insert into 表名 values (值1,值2,.....);--无限制条件的修改,会修改整张表 update 表名 set 字段 值; --有限制条件的修改,只修改特定记…

软件设计师——计算机网络(二)

&#x1f4d1;前言 本文主要是【计算机网络】——软件设计师——计算机网络的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1…

Promise介绍和使用

Promise Promise是一门新的技术&#xff08;ES6规范&#xff09;&#xff0c;JS中进行异步编程的新解决方案。&#xff08;旧的方案是使用回调函数&#xff0c;比如AJAX请求&#xff09;。 从语法上来说Promise是一个构造函数。 从功能上来说Promise对象用来封装一个异步操作并…

生成式AI赋能千行百业加速创新,2023亚马逊云科技re:Invent行业盘点

2023亚马逊云科技re:Invent全球大会已于上周圆满闭幕&#xff0c;在本次大会中&#xff0c;亚马逊云科技又为大家带来了很多功能/项目迭代更新&#xff0c;也重磅发布了很多全新的功能。今天从行业视角来盘点回顾哪些重磅发布适用于垂直行业客户&#xff0c;以及面向汽车、制造…

ChatGLM3-6B和langchain阿里云部署

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、ChatGLM3-6B部署搭建环境部署GLM3 二、Chatglm2-6blangchain部署三、Tips四、总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; …

ffmpeg之ffprobe.c源码分析一---大流程及核心代码分析

文章目录 前言为什么学习ffprobe源码源码调试main()函数重要流程函数分析open_input_file函数分析avformat_match_stream_specifier函数分析read_packets函数分析本篇文章带你打通ffprobe源码的脉络。 关注公众号免费看: 前言 注:本文章全凭个人经验以及平时学习所记录,由…

gdal合成多个波段

def synthesis_bands(dst_list, outfile):"""将多光谱波段合成一个tif:param dst_list: 输入待合成文件的列表:param outfile: 影像的输出文件夹"""dataset_init gdal.Open(dst_list[0])# 创建待输出的图tiff_driver gdal.GetDriverByName(GTi…

【MySQL进阶】索引使用

一、索引使用 1.验证索引效率 tb_sku 这张表中准备了 1000w 的记录。 我用夸克网盘分享了「1000w的模拟数据」链接&#xff1a;https://pan.quark.cn/s/15cf665202b2 这张表中id为主键&#xff0c;有主键索引&#xff0c;而其他字段是没有建立索引的。 我们先来查询其中的…

JS基础之原型原型链

JS基础之原型&原型链 原型&原型链构造函数创建对象prototypeprotoconstructor实例与原型原型的原型原型链其他constructorproto继承 原型&原型链 构造函数创建对象 我们先使用构造函数创建一个对象&#xff1a; function Person(){ } var person new Person();…

多窗口文件管理工具Q-Dir安装以及使用教程

软件介绍 Q-Dir 是一款功能强大的Windows资源管理器&#xff0c;可以非常方便的管理你的各种文件。Q-Dir有4 个窗口&#xff0c;特别适用于频繁在各个目录间跳跃复制粘贴的情况&#xff0c;每个窗口都可以方便的切换目录&#xff0c;以不同颜色区分不同类型的文件&#xff0c;…

(企业项目)微服务项目解决跨域问题:

前后端分离项目中前端出现了跨域的问题 在网关模块配置文件中添加 配置 application.properties # 允许请求来源&#xff08;老版本叫allowedOrigin&#xff09; spring.cloud.gateway.globalcors.cors-configurations.[/**].allowedOriginPatterns* # 允许携带的头信息 spri…

idea__SpringBoot微服务06——静态资源(新依赖),首页和图标定制

静态资源 一、静态资源二、首页和图标定制————————创作不易&#xff0c;如觉不错&#xff0c;随手点赞&#xff0c;关注&#xff0c;收藏(*&#xffe3;︶&#xffe3;)&#xff0c;谢谢~~ 新依赖&#xff1a;jquery的 <dependency><groupId>org.webjars&…

说说设计体系、风格指南和模式库

目录 一、定义 二、设计体系 2.1 Design system 2.2 风格指南 2.3 Component 三、样式库 一、定义 设计体系&#xff08;Design system&#xff09;&#xff1a;可共享的设计语言的基础合集&#xff0c;包含了设计价值&#xff0c;语义&#xff0c;语法和上下文。 风格…

matplotlib 默认属性和绘图风格

matplotlib 默认属性 一、绘图风格1. 绘制叠加折线图2. Solarize_Light23. _classic_test_patch4. _mpl-gallery5. _mpl-gallery-nogrid6. bmh7. classic8. fivethirtyeight9. ggplot10. grayscale11. seaborn12. seaborn-bright13. seaborn-colorblind14. seaborn-dark15. sea…