LeetCode 593. 有效的正方形(向量做法)
题目
题目链接:593. 有效的正方形
题意:给出二维平面上四个点的坐标,判断这四个点是否能构成一个正方形,四个点的输入顺序不做任何保证。
思路
通过向量运算可以很轻松地解决这道题。任取一点向其他三点连线,可以得到三个向量。我们将这三个向量按照其长度从小到大排序,分别称为 \(\boldsymbol{v}_0, \boldsymbol{v}_1, \boldsymbol{v}_2\),若满足以下三个条件,则 \(\boldsymbol{v}_0, \boldsymbol{v}_1, \boldsymbol{v}_2\) 可以“张出”一个正方形(见下图):

- \(\boldsymbol{v}_0 + \boldsymbol{v}_1 = \boldsymbol{v}_2\)(四点构成平行四边形)
- \(\Vert\boldsymbol{v}_0\Vert = \Vert\boldsymbol{v}_1\Vert\)(平行四边形 + 邻边相等,此时四点构成菱形)
- \(\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; // 构成正方形
}
}
这种使用向量运算的解法有两个好处:
- 只需要对向量做一次排序即可解决顶点不按顺序的问题,不需要分类讨论,较为简洁。
- 全程都是整数运算,不需要担心浮点运算带来的舍入误差。
本题还有其他做法:
LeetCode 593. 有效的正方形(向量做法)的更多相关文章
- C#版 - Leetcode 593. 有效的正方形 - 题解
版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...
- Java实现 LeetCode 593 有效的正方形(判断正方形)
593. 有效的正方形 给定二维空间中四点的坐标,返回四点是否可以构造一个正方形. 一个点的坐标(x,y)由一个有两个整数的整数数组表示. 示例: 输入: p1 = [0,0], p2 = [1,1] ...
- C#刷遍Leetcode面试题系列连载(5):No.593 - 有效的正方形
上一篇 LeetCode 面试题中,我们分析了一道难度为 Easy 的数学题 - 自除数,提供了两种方法.今天我们来分析一道难度为 Medium 的面试题. 今天要给大家分析的面试题是 LeetCod ...
- Leetcode 593.有效正方形
有效正方形 给定二维空间中四点的坐标,返回四点是否可以构造一个正方形. 一个点的坐标(x,y)由一个有两个整数的整数数组表示. 示例: 输入: p1 = [0,0], p2 = [1,1], p3 = ...
- [LeetCode] Maximal Square 最大正方形
Given a 2D binary matrix filled with 0's and 1's, find the largest square containing all 1's and ret ...
- [LeetCode] Valid Square 验证正方形
Given the coordinates of four points in 2D space, return whether the four points could construct a s ...
- [LeetCode]最大系列(最大正方形221,最大加号标志764)
221. 最大正方形 题目描述: 在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积. 示例: 输入: 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 ...
- Leetcode 473.火柴拼正方形
火柴拼正方形 还记得童话<卖火柴的小女孩>吗?现在,你知道小女孩有多少根火柴,请找出一种能使用所有火柴拼成一个正方形的方法.不能折断火柴,可以把火柴连接起来,并且每根火柴都要用到. 输入为 ...
- Leetcode 221.最大的正方形
最大的正方形 在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积. 示例: 输入: 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 输出 ...
随机推荐
- Java开发学习(五)----bean的生命周期
一.什么是生命周期 首先理解下什么是生命周期? 从创建到消亡的完整过程,例如人从出生到死亡的整个过程就是一个生命周期. bean生命周期是什么? bean对象从创建到销毁的整体过程. bean生命周期 ...
- nifi从入门到实战(保姆级教程)——身份认证
上一篇我们搭建好了nifi的运行环境了 但是每次登陆那一串随机字符串的用户名和密码是不是让人很头疼,那是人类能记住的吗?当然不是!!!! 那么今天我们就来消灭这些难看又难记的字符串. windows( ...
- NC24017 [USACO 2016 Jan S]Angry Cows
NC24017 [USACO 2016 Jan S]Angry Cows 题目 题目描述 Bessie the cow has designed what she thinks will be the ...
- Contest
Contest 题目 链接 题目描述 \(n\) 支队伍一共参加了三场比赛. 一支队伍 \(x\) 认为自己比另一支队伍 \(y\) 强当且仅当 \(x\) 在至少一场比赛中比 \(y\) 的排名高. ...
- Pytorch从0开始实现YOLO V3指南 part3——实现网络前向传播
本节翻译自:https://blog.paperspace.com/how-to-implement-a-yolo-v3-object-detector-from-scratch-in-pytorch ...
- Django WEB开发 - Django 3.0 Tutorial入门
1. Django 官方网站 https://docs.djangoproject.com/zh-hans/3.0/intro/tutorial01/ 2. Model View Controller ...
- LinkedList集合和Vector集合
LinkedList集合数据存储的结构是链表结构.方便元素添加.删除的集合.实际开发中对一个集合元素的添加与删除经常涉及到首尾操作,而LinkedList提供了大量首尾操作的方法 LinkedList ...
- FPS游戏逆向-方框透视(三角函数)
本套课程主要学习FPS类游戏安全 由于FPS类游戏本身的特性问题,可能产生一些通用的游戏安全问题 在通过逆向与正向对FPS类游戏分析之后,找到其可能出现的不安全点 才能更好的保护游戏不被外部力量侵犯 ...
- day01--DOS常用命令
打开CMD的方式 开始+系统+命令提示符 Win键+R输入cmd打开控制台(推荐使用) 在任意的文件夹下面,按住shift键+鼠标右键点击,在此处打开命令行窗口 资源管理器的地址栏前面加,上cmd路径 ...
- C++ 加速(卡常)技巧【超级 快读、快写】
C++ \texttt{C++} C++ 加速技巧 快读快写 快读 inline int read() { int x = 0, w = 0; char ch = 0; while (!isdigit ...