题解:有效的正方形

题解:有效的正方形

题目分析

题目描述

给定二维空间中四个点的坐标 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. 算法优势:时间/空间复杂度均为常数级,逻辑简洁、执行高效,是该问题的最优解法。
相关推荐
倒头就睡的小比特1 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!1 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
晨米酱1 天前
AGENTS.md:Agent 的上下文策略层
面试·架构·agent
猎头南楼1 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
AI产品测评官1 天前
海内外AI招聘工具分赛道横向对比:五大品类的技术路线与选型参考
人工智能·ai·求职招聘
旖旎夜光1 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark1 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her11 天前
并查集-听课笔记
笔记·算法·并查集
码流子1 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
彧azz1 天前
Linux 环境下 Redis 学习总结:数据类型、持久化、锁、事务、主从与缓存问题
linux·redis·笔记·学习·面试