题目

题目链接: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 语言的题解代码。

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

  1. /// 二维向量
  2. #[derive(Copy, Clone, Eq, PartialEq)]
  3. struct Vector {
  4. x: i32,
  5. y: i32
  6. }
  7. impl Vector {
  8. fn new(from: (i32, i32), to: (i32, i32)) -> Self { Vector { x: to.0 - from.0, y: to.1 - from.1 } }
  9. /// 向量的模的平方
  10. fn len2(&self) -> i32 { self.x * self.x + self.y * self.y }
  11. }
  12. impl std::ops::Mul for Vector {
  13. type Output = i32;
  14. /// 向量点乘
  15. fn mul(self, rhs: Self) -> Self::Output { self.x * rhs.x + self.y * rhs.y }
  16. }
  17. impl std::ops::Add for Vector {
  18. type Output = Vector;
  19. /// 向量加法
  20. fn add(self, rhs: Self) -> Self::Output { Vector { x: self.x + rhs.x, y: self.y + rhs.y } }
  21. }

解题函数如下:

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

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

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

本题还有其他做法:

LeetCode 593. 有效的正方形(向量做法)的更多相关文章

  1. C#版 - Leetcode 593. 有效的正方形 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  2. Java实现 LeetCode 593 有效的正方形(判断正方形)

    593. 有效的正方形 给定二维空间中四点的坐标,返回四点是否可以构造一个正方形. 一个点的坐标(x,y)由一个有两个整数的整数数组表示. 示例: 输入: p1 = [0,0], p2 = [1,1] ...

  3. C#刷遍Leetcode面试题系列连载(5):No.593 - 有效的正方形

    上一篇 LeetCode 面试题中,我们分析了一道难度为 Easy 的数学题 - 自除数,提供了两种方法.今天我们来分析一道难度为 Medium 的面试题. 今天要给大家分析的面试题是 LeetCod ...

  4. Leetcode 593.有效正方形

    有效正方形 给定二维空间中四点的坐标,返回四点是否可以构造一个正方形. 一个点的坐标(x,y)由一个有两个整数的整数数组表示. 示例: 输入: p1 = [0,0], p2 = [1,1], p3 = ...

  5. [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 ...

  6. [LeetCode] Valid Square 验证正方形

    Given the coordinates of four points in 2D space, return whether the four points could construct a s ...

  7. [LeetCode]最大系列(最大正方形221,最大加号标志764)

    221. 最大正方形 题目描述: 在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积. 示例: 输入: 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 ...

  8. Leetcode 473.火柴拼正方形

    火柴拼正方形 还记得童话<卖火柴的小女孩>吗?现在,你知道小女孩有多少根火柴,请找出一种能使用所有火柴拼成一个正方形的方法.不能折断火柴,可以把火柴连接起来,并且每根火柴都要用到. 输入为 ...

  9. 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 输出 ...

随机推荐

  1. 一个 curl 配置引发的惨案

    问题 这两天想装新版本的 node,发现 nvm 一直报下面这个错误.我反复 Google 了,但是并没有找到一条我能用的. 痛苦 我起初一直怀疑是我用的 zsh-nvm 抽疯,所以今天有空就把它还有 ...

  2. C++ 智能指针浅析

    C++ 智能指针浅析 为了解决 C++ 中内存管理这个老大难问题,C++ 11 中提供了三种可用的智能指针.(早期标准库中还存在一种 auto_ptr,但由于设计上的缺陷,已经被 unique_ptr ...

  3. SQL的语法

    SQL的语法 SQL通用语法 SQL语句可以单行或多行书写,以分号(";")结尾. SQL语句可以使用空格或缩进增强可读性. MySQL数据库的SQL语句不区分大小写(建议关键字大 ...

  4. 探索链路追踪在.NET6工业物联网项目的应用

    ExploringIoTDistributedTracingNet6 如果觉得有用,请留言学到了. 已经会了的老哥,请留言就这? 可能遇到的问题 工业物联网项目自上而下一般分为ERP.Mes.SCAD ...

  5. robotframework之环境安装

    一.安装python2.7环境,python --version查询python安装的版本 二.setuptools安装

  6. opencv-python保存视频

    import cv2 class WVideoManager: def __init__(self, write_path: str, width: int, height: int, FPS: in ...

  7. node zlib压缩模块了解一下

    压缩: 从index.html压缩成index.html.gz const zlib = require('zlib'); const gzip = zlib.createGzip();const f ...

  8. UiPathExcel写入操作

    一.Excel 写操作 1.写一个单元格 (1)控件介绍 Write Cell: 使用Write Cell控件,在指定单元格写入内容     常用属性介绍: Destination: Cell: 要写 ...

  9. UiPath剪贴板操作的介绍和使用

    一.剪切板操作的介绍 模拟用户使用剪切板操作的一种行为: 例如使用设置剪切板(SettoClipboard),从剪切板获取(GetfromClipboard)的操作 二.剪切板相关操作在UiPath中 ...

  10. 如何搭建android源代码repo仓库

    如何搭建android源代码repo仓库 目录 如何搭建android源代码repo仓库 1 repo是如何管理仓库的? 1.1 repo如何工作的? 1.2 搭建repo服务需要做哪些事情? 2 部 ...