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

文章目录

    • @[toc]
      • 问题描述
      • 一维最接近点对算法
        • `Python`实现
      • 二维最接近点对算法
        • 分治算法
        • 时间复杂性
        • `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}')
最接近的点对为: (1, 2)

二维最接近点对算法

分治算法
  • 选取一垂直线 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}')
最接近的点对为: ((2, 3), (3, 4)), 点对距离为 1.4142135623730951

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

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

相关文章

python 打包为exe可执行程序

近期因为需要做文字识别&#xff0c;应用ocr 所以每次都需要部署环境&#xff0c;然后打算做成exe&#xff0c;遇到问题做一总结。 pyinstaller -D --hidden-importpaddleocr testflask.py 生成exe paddleocr 和pyinstaller 安装不做说明。 No such file or directory: …

Web开发小知识点(一)

1.input不支持自动换行解决办法 input不支持换行&#xff1b; textarea&#xff1a;支持换行&#xff1b; 设置提示文案的css 用&#xff1a;&#xff1a;placeHolder 2.textarea禁止拖拽、去掉右下角三角&#xff08;css下&#xff09; textarea{resize:none; } 3.用户对访…

web 基础之 HTTP 请求

web 基础 网上冲浪 就是在互联网(internet)上获取各种信息&#xff0c;进行工作&#xff0c;或者娱乐&#xff0c;他的英文表示surfing the Internet&#xff0c;因 “surfing”d的意思是冲浪&#xff0c;即成为网上冲浪&#xff0c;这是一种形象说法&#xff0c; 也是一个非…

市场营销的酒店营销策略研究意义

在市场经济条件下&#xff0c;市场营销策略已成为企业经营管理中最重要的组成部分&#xff0c;其在企业管理中的地位日益显现出来。 然而&#xff0c;由于酒店营销环境的特殊性&#xff0c;酒店营销策略研究一直是咱们从业者研究的热点之一。 对于酒店营销策略的研究&#xf…

MySQL中JOIN连接的实现算法

目录 嵌套循环算法&#xff08;NLJ&#xff09; 简单嵌套循环&#xff08;SNLJ&#xff09; 索引嵌套循环&#xff08;INLJ&#xff09; 块嵌套循环&#xff08;BNLJ&#xff09; 三种算法比较 哈希连接算法&#xff08;Hash Join&#xff09; 注意事项&#xff1a; 工…

VS2022快捷键修改

VS2022快捷键修改 VS2022快捷键修改 VS2022快捷键修改

【LAMMPS学习】八、基础知识(5.11)磁自旋

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

如何使用 iOS系统恢复软件修复 iPhone 问题

苹果公司向世界推出了他们可以拥有的最智能的手机。但即使是 iPhone 也无法避免智能手机常见的损坏和问题。您将熟悉最常见的问题。屏幕黑屏或卡在 Apple 徽标上&#xff1b;冻结或卡在恢复模式的 iPhone。但这样的问题不胜枚举&#xff0c;每天都有 iOS 用户在他们的设备中遇到…

STM32-DAC

DAC 前言一、理论介绍二、DAC代码三、实验结果总结 前言 前言写个参考吧 STM32 DAC串口 一、理论介绍 DAC是数字模拟转换器&#xff08;Digital to Analog Converter&#xff09;的缩写&#xff0c;它是一种将数字信号转换为模拟信号的设备。 RC有2个通道。 DAC的初始化 #…

【idea-sprongboot项目】在linux服务器上纯远程开发方式

继上一篇博客【idea-sprongboot项目】SSH连接云服务器进行远程开发-CSDN博客 目录 五、远程开发方式 2&#xff09;纯远程开发方式 步骤 五、远程开发方式 2&#xff09;纯远程开发方式 实现原理&#xff0c; 步骤 &#xff08;1&#xff09;首先&#xff0c;关闭当前正在…

【k8s多集群管理平台开发实践】八、client-go实现service读取列表、创建service、读取yaml配置并更新

文章目录 简介 一.k8s的service列表1.1.controllers控制器代码1.2.models模型代码 二.创建service2.1.controllers控制器代码2.2.models模分代码 三.读取和更新service的yaml配置3.1.controllers控制器代码3.2.models模型代码 四.路由设置4.1.路由设置 五.前端代码5.1.列表部分…

向各位请教一个问题

这是菜鸟上的一道题目&#xff0c;单单拿出来问问大家&#xff0c;看看能不能解惑 &#xff0c;谢谢各位&#xff01; 题目25&#xff1a;求12!3!...20!的和 解题思路&#xff1a;这个题不知道为什么我用DEV C 5.11显示出来为0.000000&#xff0c;可能版本有问题&#xff1f;&a…