题解:有效的正方形

题解:有效的正方形

题目分析

题目描述

给定二维空间中四个点的坐标 p1, p2, p3, p4(坐标无固定顺序),判断这四个点能否构成一个有效的正方形。有效正方形需满足核心条件:四条边长度相等,四个内角均为90度直角。

核心难点

  1. 输入的四个点无固定顺序,无法直接按"边的顺序"判断;
  2. 直接计算两点间距离会引入浮点数精度误差(如√2是无理数,开平方后无法精确表示);
  3. 需排除特殊无效情况(如四点重合、三点共线、仅三条边相等但对角线不满足直角条件等)。

关键数学性质(正方形的充要条件)

对于无顺序的四个点,若能构成正方形,则其所有两两组合的距离(共 C(4,2)=6 组)满足:

  1. 最小距离不为0(排除重合点);
  2. 6个距离中仅包含两种数值:
    • 较小值(边长)出现4次(对应正方形的四条边);
    • 较大值(对角线)出现2次(对应正方形的两条对角线);
  3. 对角线长度的平方 = 2 × 边长长度的平方(由勾股定理推导,直角三角形斜边平方等于两直角边平方和)。

解题思路

基于上述数学性质,核心思路是用距离平方替代实际距离(规避浮点数精度误差),通过统计6组两两距离平方的特征完成判断:

  1. 定义辅助函数,计算两点间距离的平方(避免开平方操作);
  2. 遍历四个点的所有两两组合,计算6组距离平方并存储;
  3. 对距离平方数组排序,便于快速验证特征:
    • 排序后前4个元素为"边长平方",后2个为"对角线平方";
    • 验证核心条件:最小距离平方≠0、前4个值相等、后2个值相等、对角线平方=2×边长平方。

代码实现(带详细注释)

cpp 复制代码
#include <vector>
#include <algorithm>
using namespace std;

class Solution {
public:
    // 辅助函数:计算两点间距离的平方(避免浮点数精度误差)
    long long get_distance(vector<int>& p1, vector<int>& p2) {
        // 用long long避免int溢出(坐标差值的平方可能超出int范围)
        long long dx = p1[0] - p2[0]; // x轴坐标差值
        long long dy = p1[1] - p2[1]; // y轴坐标差值
        return dx * dx + dy * dy;     // 距离平方公式:(x1-x2)² + (y1-y2)²
    }

    bool validSquare(vector<int>& p1, vector<int>& p2, vector<int>& p3, vector<int>& p4) {
        // 将四个点存入数组,方便遍历所有两两组合
        vector<vector<int>> points = {p1, p2, p3, p4};
        // 存储6组两两距离的平方
        vector<long long> distance_squares;

        // 遍历所有两两组合(i<j避免重复计算),共C(4,2)=6组
        for (int i = 0; i < 4; ++i) {
            for (int j = i + 1; j < 4; ++j) {
                distance_squares.push_back(get_distance(points[i], points[j]));
            }
        }

        // 排序后:前4个为边长平方,后2个为对角线平方
        sort(distance_squares.begin(), distance_squares.end());

        // 核心判断逻辑:逐一验证正方形的数学特征
        return distance_squares[0] != 0          // 条件1:无重合点(最小距离不为0)
               && distance_squares[0] == distance_squares[1]  // 条件2:前4个边长平方相等
               && distance_squares[1] == distance_squares[2]
               && distance_squares[2] == distance_squares[3]
               && distance_squares[4] == distance_squares[5]  // 条件3:两个对角线平方相等
               && 2 * distance_squares[0] == distance_squares[4]; // 条件4:对角线平方=2×边长平方
    }
};

代码关键解释

  1. 辅助函数 get_distance

    • 核心作用:计算两点间距离的平方,彻底避免开平方操作带来的浮点数精度问题;
    • 数据类型选择:使用long long而非int,防止坐标差值较大时(如差值为1e4),平方运算超出int的取值范围导致溢出。
  2. 遍历两两组合

    • 采用i < j的双层循环,确保每个点对只计算一次,最终得到6组距离平方(对应4个点的所有两两组合),无重复、无遗漏。
  3. 排序与条件判断

    • 排序后数组的前4个元素对应正方形四条边的平方,后2个对应两条对角线的平方,通过连续的相等判断可快速验证"四边相等、对角线相等";
    • 最后验证"对角线平方=2×边长平方",确保四个角为90度,排除"菱形(四边相等但非直角)"的无效情况。

复杂度分析

  • 时间复杂度 :O(1)。

    四个点的两两组合固定为6组,计算距离平方的操作是常数级;排序6个元素的时间复杂度为常数(排序固定数量的元素无渐近复杂度),因此整体时间复杂度为O(1)。

  • 空间复杂度 :O(1)。

    仅使用固定大小的数组存储4个点和6个距离平方,无动态扩容的空间开销,空间复杂度为常数级。

测试用例验证

输入点坐标 输出 说明
[0,0],[1,1],[1,0],[0,1] true 标准正方形
[0,0],[0,0],[0,0],[0,0] false 四点重合
[0,0],[1,2],[3,1],[2,-1] false 菱形(边长相等但非直角)
[1,0],[-1,0],[0,1],[0,-1] true 以原点为中心的正方形

总结

  1. 核心技巧:用距离平方替代实际距离,彻底规避浮点数精度误差,是解决几何距离判定问题的常用手段;
  2. 判定逻辑:通过排序后统计距离平方的分布特征,精准匹配正方形的数学性质,覆盖所有边界情况;
  3. 算法优势:时间/空间复杂度均为常数级,逻辑简洁、执行高效,是该问题的最优解法。
相关推荐
你撅嘴真丑2 小时前
习题与总结
算法
Getgit2 小时前
Linux 下查看 DNS 配置信息的常用命令详解
linux·运维·服务器·面试·maven
亲爱的非洲野猪2 小时前
动态规划进阶:状态机DP深度解析
算法·动态规划
dragoooon342 小时前
[hot100 NO.91~95]
算法
June bug2 小时前
(#字符串处理)字符串中第一个不重复的字母
python·leetcode·面试·职场和发展·跳槽
windows_62 小时前
【无标题】
算法
踢足球09293 小时前
寒假打卡:2026-01-24
数据结构·算法
Anastasiozzzz3 小时前
Redis的键过期是如何删除的?【面试高频】
java·数据库·redis·缓存·面试
亲爱的非洲野猪3 小时前
动态规划进阶:多维DP深度解析
算法·动态规划