首页 > 其他分享 >LeetCode 593. 有效的正方形(向量做法)

LeetCode 593. 有效的正方形(向量做法)

时间:2022-08-22 23:34:55浏览次数:74  
标签:593 p1 i32 self boldsymbol 正方形 Vector LeetCode 向量

题目

题目链接:593. 有效的正方形

题意:给出二维平面上四个点的坐标,判断这四个点是否能构成一个正方形,四个点的输入顺序不做任何保证。

思路

通过向量运算可以很轻松地解决这道题。任取一点向其他三点连线,可以得到三个向量。我们将这三个向量按照其长度从小到大排序,分别称为 \(\boldsymbol{v}_0, \boldsymbol{v}_1, \boldsymbol{v}_2\),若满足以下三个条件,则 \(\boldsymbol{v}_0, \boldsymbol{v}_1, \boldsymbol{v}_2\) 可以“张出”一个正方形(见下图):

  1. \(\boldsymbol{v}_0 + \boldsymbol{v}_1 = \boldsymbol{v}_2\)(四点构成平行四边形)
  2. \(\Vert\boldsymbol{v}_0\Vert = \Vert\boldsymbol{v}_1\Vert\)(平行四边形 + 邻边相等,此时四点构成菱形)
  3. \(\boldsymbol{v}_0 \cdot \boldsymbol{v}_1 = 0\)(菱形 + 直角,此时四点构成正方形)

我们还需要特别注意排除点重合的情况,例如四个点全部重合在一起,此时上面的三个条件仍然满足,但是不能构成正方形。

代码

以下为 Rust 语言的题解代码。

首先我们需要定义一个二维向量类型:

/// 二维向量
#[derive(Copy, Clone, Eq, PartialEq)]
struct Vector {
    x: i32,
    y: i32
}

impl Vector {
    fn new(from: (i32, i32), to: (i32, i32)) -> Self { Vector { x: to.0 - from.0, y: to.1 - from.1 } }
    /// 向量的模的平方
    fn len2(&self) -> i32 { self.x * self.x + self.y * self.y }
}

impl std::ops::Mul for Vector {
    type Output = i32;
    /// 向量点乘
    fn mul(self, rhs: Self) -> Self::Output { self.x * rhs.x + self.y * rhs.y }
}

impl std::ops::Add for Vector {
    type Output = Vector;
    /// 向量加法
    fn add(self, rhs: Self) -> Self::Output { Vector { x: self.x + rhs.x, y: self.y + rhs.y } }
}

解题函数如下:

impl Solution {
    pub fn valid_square(p1: Vec<i32>, p2: Vec<i32>, p3: Vec<i32>, p4: Vec<i32>) -> bool {
        let mut v = [
            Vector::new((p1[0], p1[1]), (p2[0], p2[1])),
            Vector::new((p1[0], p1[1]), (p3[0], p3[1])),
            Vector::new((p1[0], p1[1]), (p4[0], p4[1]))
        ];
        v.sort_by_key(Vector::len2);
        return v[0].len2() > 0            // 点不重合
            && v[0] + v[1] == v[2]        // 构成平行四边形
            && v[0].len2() == v[1].len2() // 构成菱形
            && v[0] * v[1] == 0;          // 构成正方形
    }
}

这种使用向量运算的解法有两个好处:

  • 只需要对向量做一次排序即可解决顶点不按顺序的问题,不需要分类讨论,较为简洁。
  • 全程都是整数运算,不需要担心浮点运算带来的舍入误差。

本题还有其他做法:

标签:593,p1,i32,self,boldsymbol,正方形,Vector,LeetCode,向量
From: https://www.cnblogs.com/zhb2000/p/leetcode-valid-square.html

相关文章

  • leetcode48-旋转图像
    旋转图像原地旋转将正方形的数组切分成一个个圈,然后对这个圈进行移动classSolution{publicvoidrotate(int[][]matrix){intn=matrix.length;......
  • LeetCode 367. 有效的完全平方数
    LeetCode367.有效的完全平方数思路:核心为最后一步判断当二分结束后值为及接近一个整数的浮点数(如2.9xxxx)此时加上极小数(1e-6)取整再平方,若与num相等则为完全平方数......
  • LeetCode 69. x 的平方根
    LeetCode69.x的平方根思路:浮点数二分修改版因为返回的是整数所以二分分三类讨论mid*mid==x该情况mid为x的平方根mid*mid>x该情况mid大于x的平方根mid......
  • LeetCode 34. 在排序数组中查找元素的第一个和最后一个位置
    34.在排序数组中查找元素的第一个和最后一个位置思路:与AcWing789一致classSolution{public:vector<int>searchRange(vector<int>&nums,inttarget){......
  • LeetCode 35. 搜索插入位置
    LeetCode35.搜索插入位置思路直接利用二分模板注意右指针开始为nums.size()而不是nums.size()-1因为有可能在最后一位插入classSolution{public:intsearc......
  • [Google] LeetCode 1937 Maximum Number of Points with Cost
    Youaregivenanmxnintegermatrixpoints(0-indexed).Startingwith0points,youwanttomaximizethenumberofpointsyoucangetfromthematrix.Togai......
  • LeetCode 811. Subdomain Visit Count
    原题链接在这里:https://leetcode.com/problems/subdomain-visit-count/题目:Awebsitedomain "discuss.leetcode.com" consistsofvarioussubdomains.Atthetople......
  • [Google] LeetCode 729 My Calendar I
    Youareimplementingaprogramtouseasyourcalendar.Wecanaddaneweventifaddingtheeventwillnotcauseadoublebooking.Adoublebookinghappenswh......
  • LeetCode 1472. Design Browser History
    原题链接在这里:https://leetcode.com/problems/design-browser-history/题目:Youhavea browser ofonetabwhereyoustartonthe homepage andyoucanvisitan......
  • [Google] LeetCode 2013 Detect Squares
    YouaregivenastreamofpointsontheX-Yplane.Designanalgorithmthat:Addsnewpointsfromthestreamintoadatastructure.Duplicatepointsareallow......