题目描述

✅ 612. 平面上的最近距离

题意分析

表中的 (x, y) 表示平面上的点,要求任意两个不同点之间的最短欧氏距离,并把结果四舍五入到两位小数,输出列名为 shortest。

需要比较的是点对,不能让一个点和自己配对,否则零距离会成为错误答案。当前官方题目的表名为 Point2D,下面按这个名字查询。

解法:SQL 自连接枚举点对

核心思路

[!blue]
为同一张点表指定 p1、p2 两个别名,自连接就可以枚举两个点的组合。为了排除自身,并避免把同一对点正反算两次,只保留坐标按字典序递增的方向:p1.x < p2.x,或者横坐标相同且 p1.y < p2.y。

对任意两个不同坐标,若横坐标不同,只有横坐标较小的点放在前面时成立;若横坐标相同,则由纵坐标决定唯一方向。因此每对不同点都被保留一次,竖直方向的点对也不会遗漏。

每对点的距离为 $\sqrt{(x_1-x_2)^2+(y_1-y_2)^2}$,对应 SQL 中的 SQRT 与 POW。用 MIN 从所有点对中取最短距离,再由外层 ROUND(..., 2) 统一四舍五入。没有按点分组,结果只有一个全局最短值。

解题步骤

  1. 用 p1、p2 两个别名自连接 Point2D。
  2. 按 x、y 字典序只保留一个方向的不同点对。
  3. 计算距离并取最小值。
  4. 保留两位小数,设置结果列名。

代码实现

SELECT ROUND(
    -- ROUND 套在 MIN 外面:先取精确最小值,最后一次性格式化。
    MIN(SQRT(POW(p1.x - p2.x, 2) + POW(p1.y - p2.y, 2))),
    2
) AS shortest
FROM Point2D p1
JOIN Point2D p2
-- 严格字典序:既排除「点与自己配对」,又保证每对点只出现一次。
-- 后半段不可省,否则所有横坐标相同的竖直点对都会被丢掉。
ON (p1.x < p2.x) OR (p1.x = p2.x AND p1.y < p2.y);

复杂度分析

  • 时间复杂度:按点对枚举的执行方式为 $O(n²)$,具体执行成本取决于查询计划。
  • 空间复杂度:MIN 本身仅需常数状态,其他连接或物化工作空间由执行计划决定。

关键点总结

[!green]

  • 同 x 的点也可能构成最近点对。
  • 严格顺序同时排除自身配对与反向重复。
  • 输出是全局最短值,不是按点或坐标分组的结果。

易错点总结

[!yellow]

  • 连接不排除自身:零距离污染最小值。
  • 条件只有 x 小于:遗漏竖直点对。
  • 使用曼哈顿距离:计算的不是题目要求的欧氏距离。
  • 增加 GROUP BY:输出粒度发生改变。

相似题目

题目 难度 关联与区别
613. 直线上的最近距离 简单 原题点在一维线上,排序相邻差即可,本题二维点对需比较欧氏距离。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2021/50066874
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!