郭震 AI公众号:郭震AI

9 几何算法之最近点对问题

发布日期:

最近更新:

分类: 计算几何

预计阅读: 3 分钟

阅读次数: 0

系列进度

计算几何入门 · 第 9 / 18

预计阅读3 分钟
结构重点8 个
图文要点6 张
正文规模1.3k 字

整理说明

这篇内容怎么整理

郭震 · 2026-06-04

独立整理围绕 8 个结构重点拆成环境、步骤、验证点和常见误区,尽量让读者能照着复现。
图文对照保留 6 张和配置、流程、判断结果有关的图片,方便快速定位正文重点。
持续校对工具、模型和命令变化较快,后续优先修正入口、参数和风险提醒。

阅读路线

先按这条路线读

先抓住主线,再回到代码、配置和图文细节,读起来会更稳。

图文要点

先看本文图文节点

按图先建立主线,再跳回正文核对步骤、配置和判断标准。

几何算法之最近点对问题结构图查看大图
几何算法之最近点对问题结构图

计算几何适合用图来理解,关键是把几何对象、关系判断和算法边界放在一起看。阅读时可以按「问题定义 -> 朴素方法 -> 分治法 -> 思路」建立结构,再回到正文里的代码、案例或指标做验证。

几何算法之最近点对问题核对图查看大图
几何算法之最近点对问题核对图

读完后,用一个真实小任务复查:输入是什么,处理环节在哪里,输出是否可验收;失败时先查「问题定义」,再查「朴素方法」。

在本章中,我们将探讨计算几何中的一个经典问题:最近点对问题。该问题旨在找到平面或空间中距离最近的一对点。它在诸多应用中具有重要意义,如碰撞检测、路径规划及数据压缩等。

问题定义

给定一个点集 P={p1,p2,,pn}P = \{p_1, p_2, \ldots, p_n\},每个点 pip_i 在平面中的坐标为 (xi,yi)(x_i, y_i),我们需要找到两个点 pip_ipjp_j,使得它们之间的距离最小,即求解以下最小值:

最近点对问题判断卡查看大图
最近点对问题判断卡

学习最近点对问题时,先看暴力比较的成本,再看按坐标排序、分治合并和候选带筛选如何减少计算。

d(pi,pj)=(xixj)2+(yiyj)2d(p_i, p_j) = \sqrt{(x_i - x_j)^2 + (y_i - y_j)^2}

朴素方法

最简单的方法是使用一个双重循环来检查所有点对的距离,时间复杂度为 O(n2)O(n^2)。具体实现如下:

def naive_closest_pair(points):
    n = len(points)
    min_distance = float('inf')
    closest_pair = (None, None)

    for i in range(n):
        for j in range(i + 1, n):
            distance = ((points[i][0] - points[j][0]) ** 2 + 
                         (points[i][1] - points[j][1]) ** 2) ** 0.5
            if distance < min_distance:
                min_distance = distance
                closest_pair = (points[i], points[j])
    
    return closest_pair, min_distance

然而,该算法对于大规模数据集效率极低,因此我们需要更高效的解决方案。

分治法

思路

计算几何阅读地图卡查看大图
计算几何阅读地图卡

《几何算法之最近点对问题》适合边看图边读正文。先确认问题和判断标准,再看概念解释与练习步骤,信息会更容易连成一条线。

我们可以利用分治法来减少时间复杂度。该方法的基本思路是将点集分为两半,然后递归地找到每一半中的最近点对。同时,我们还需考虑可能跨越两个子集的最近点对。

算法步骤

  1. 分割:将点集 PP 按照 x 坐标排序,并划分为两个子集 PLP_LPRP_R
  2. 递归求解:递归地求解子集 PLP_LPRP_R 中的最近点对,分别记为 (pL1,pL2)(p_{L1}, p_{L2})(pR1,pR2)(p_{R1}, p_{R2})
  3. 合并:设 dLd_LdRd_R 为子集的最小距离。取 d=min(dL,dR)d = \min(d_L, d_R)
  4. 创建一个带宽为 dd 的矩形带,检查该带内的点,找到跨子集的最近点对。

关键实现

在合并过程中,我们只需要检查带内的点。以下是完整的实现代码:

def closest_pair(points):
    def distance(p1, p2):
        return ((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2) ** 0.5
    
    def find_closest_util(points_sorted_by_x, points_sorted_by_y):
        if len(points_sorted_by_x) <= 3:
            return naive_closest_pair(points_sorted_by_x)
        
        mid = len(points_sorted_by_x) // 2
        midpoint = points_sorted_by_x[mid]
        
        left_y = [p for p in points_sorted_by_y if p[0] <= midpoint[0]]
        right_y = [p for p in points_sorted_by_y if p[0] > midpoint[0]]
        
        (p1, p2, left_dist) = find_closest_util(points_sorted_by_x[:mid], left_y)
        (p3, p4, right_dist) = find_closest_util(points_sorted_by_x[mid:], right_y)
        
        min_dist = min(left_dist, right_dist)
        closest_pair = (p1, p2) if left_dist < right_dist else (p3, p4)

        in_strip = [p for p in points_sorted_by_y if abs(p[0] - midpoint[0]) < min_dist]

        for i in range(len(in_strip)):
            for j in range(i + 1, len(in_strip)):
                if (in_strip[j][1] - in_strip[i][1]) < min_dist:
                    d = distance(in_strip[i], in_strip[j])
                    if d < min_dist:
                        min_dist = d
                        closest_pair = (in_strip[i], in_strip[j])
                else:
                    break

        return closest_pair[0], closest_pair[1], min_dist

    points_sorted_by_x = sorted(points, key=lambda x: x[0])
    points_sorted_by_y = sorted(points, key=lambda x: x[1])
    
    return find_closest_util(points_sorted_by_x, points_sorted_by_y)

# 使用示例
points = [(0, 0), (1, 1), (2, 2), (3, 1), (1, 3)]
closest_pair_result = closest_pair(points)
print("最近点对:", closest_pair_result[:2], "距离:", closest_pair_result[2])

时间复杂度

使用分治法的时间复杂度为 O(nlogn)O(n \log n),这是因为在分割阶段需要 O(nlogn)O(n \log n) 的时间,而在合并阶段最多需要 O(n)O(n) 的时间。这使得该算法在大型数据集处理时远远优于朴素方法。

应用案例

最近点对问题在许多实际应用中都有广泛应用:

几何算法之最近点对问题应用检查卡查看大图
几何算法之最近点对问题应用检查卡

练习《几何算法之最近点对问题》时,建议把输入条件、处理动作和可见结果写在一起,方便下次复查。

几何算法之最近点对问题应用复盘卡查看大图
几何算法之最近点对问题应用复盘卡

复习《几何算法之最近点对问题》时,建议把关键概念、操作步骤和可见结果放在同一页里回看。

  • 图像处理:可以用于特征点匹配。
  • 点云处理:在3D建模中帮助寻找最近邻点,优化模型。
  • 电子商务:基于用户行为数据评估用户之间的相似性和相距问题,以提高推荐系统性能。

以上是关于最近点对问题的详细解析及实现,接下来我们将探讨与此相关的凸包算法,进一步扩展对于空间中点集的处理策略。

继续阅读

从这篇继续找到相关教程

AI 教程总索引

常见问题

读前先确认这三点

几何算法之最近点对问题适合谁读?

这是 计算几何入门 系列第 9 / 18 篇,适合正在学习计算几何入门,并且需要把概念落到操作步骤或判断标准里的读者。

读这篇计算几何入门教程要多久?

按中文技术文章阅读速度估算,通读大约 3 分钟;如果要跟着复现,建议把命令、配置和结果检查分开做。

这篇文章里的图文节点怎么用?

正文里有 6 个图文节点,可以先用它们抓住流程、配置和判断点,再回到对应段落细读。

分享文章

转发到常用平台

微信/朋友圈可先复制链接

相关教程

AI 教程总索引

继续阅读

继续找到相关 AI 教程

返回栏目

Reader Messages

读者留言

有问题、补充资料或实测结果,可以直接留下。这里不需要登录。

最多 800 字

为了防刷,每条留言会做长度、链接数量和提交频率限制。

0/800

留言列表

0
正在加载留言...