Medium
题目描述
给定二维空间中四个点的坐标 p1, p2, p3 和 p4,如果这四个点构成一个正方形,则返回 true。
点 pi 的坐标表示为 [xi, yi]。输入没有按任何顺序给出。
有效的正方形具有四条长度相等的边(边长为正数)和四个相等的角(90度角)。
示例 1:
输入: p1 = [0,0], p2 = [1,1], p3 = [1,0], p4 = [0,1]
输出: true
示例 2:
输入: p1 = [0,0], p2 = [1,1], p3 = [1,0], p4 = [0,12]
输出: false
示例 3:
输入: p1 = [1,0], p2 = [-1,0], p3 = [0,1], p4 = [0,-1]
输出: true
提示:
- p1.length == p2.length == p3.length == p4.length == 2
- -10^4 <= xi, yi <= 10^4
解题思路
解题思路
判断四个点是否构成正方形,关键在于验证正方形的几何特性:
- 四条边相等且长度大于0
- 两条对角线相等
- 对角线长度是边长的√2倍
方法一:距离分析法(推荐)
计算任意两点间的距离,正方形应该有4条相等的边和2条相等的对角线。具体步骤:
- 计算所有点对之间的距离的平方(避免浮点运算)
- 对距离进行排序
- 检查是否恰好有4个相等的较小距离(边)和2个相等的较大距离(对角线)
- 验证对角线长度是边长的2倍(因为我们用的是距离的平方)
方法二:向量法
选择一个点作为基准,计算到其他三个点的向量,验证是否存在两个垂直且等长的向量。
方法三:中心点法
计算四个点的中心,验证所有点到中心的距离相等,且相邻点之间的夹角为90度。
距离分析法最直观且容易实现,是最推荐的解法。
代码实现
class Solution {
public:
bool validSquare(vector<int>& p1, vector<int>& p2, vector<int>& p3, vector<int>& p4) {
vector<vector<int>> points = {p1, p2, p3, p4};
vector<long long> distances;
// 计算所有点对之间的距离的平方
for (int i = 0; i < 4; i++) {
for (int j = i + 1; j < 4; j++) {
long long dx = points[i][0] - points[j][0];
long long dy = points[i][1] - points[j][1];
distances.push_back(dx * dx + dy * dy);
}
}
sort(distances.begin(), distances.end());
// 正方形应该有4条相等的边和2条相等的对角线
// 边长不能为0,对角线长度应该是边长的√2倍(平方后是2倍)
return distances[0] > 0 &&
distances[0] == distances[1] &&
distances[1] == distances[2] &&
distances[2] == distances[3] &&
distances[4] == distances[5] &&
distances[0] * 2 == distances[4];
}
};
class Solution:
def validSquare(self, p1: List[int], p2: List[int], p3: List[int], p4: List[int]) -> bool:
points = [p1, p2, p3, p4]
distances = []
# 计算所有点对之间的距离的平方
for i in range(4):
for j in range(i + 1, 4):
dx = points[i][0] - points[j][0]
dy = points[i][1] - points[j][1]
distances.append(dx * dx + dy * dy)
distances.sort()
# 正方形应该有4条相等的边和2条相等的对角线
# 边长不能为0,对角线长度应该是边长的√2倍(平方后是2倍)
return (distances[0] > 0 and
distances[0] == distances[1] == distances[2] == distances[3] and
distances[4] == distances[5] and
distances[0] * 2 == distances[4])
public class Solution {
public bool ValidSquare(int[] p1, int[] p2, int[] p3, int[] p4) {
int[][] points = {p1, p2, p3, p4};
List<long> distances = new List<long>();
// 计算所有点对之间的距离的平方
for (int i = 0; i < 4; i++) {
for (int j = i + 1; j < 4; j++) {
long dx = points[i][0] - points[j][0];
long dy = points[i][1] - points[j][1];
distances.Add(dx * dx + dy * dy);
}
}
distances.Sort();
// 正方形应该有4条相等的边和2条相等的对角线
// 边长不能为0,对角线长度应该是边长的√2倍(平方后是2倍)
return distances[0] > 0 &&
distances[0] == distances[1] &&
distances[1] == distances[2] &&
distances[2] == distances[3] &&
distances[4] == distances[5] &&
distances[0] * 2 == distances[4];
}
}
/**
* @param {number[]} p1
* @param {number[]} p2
* @param {number[]} p3
* @param {number[]} p4
* @return {boolean}
*/
var validSquare = function(p1, p2, p3, p4) {
const points = [p1, p2, p3, p4];
const distances = [];
// 计算所有点对之间的距离的平方
for (let i = 0; i < 4; i++) {
for (let j = i + 1; j < 4; j++) {
const dx = points[i][0] - points[j][0];
const dy = points[i][1] - points[j][1];
distances.push(dx * dx + dy * dy);
}
}
distances.sort((a, b) => a - b);
// 正方形应该有4条相等的边和2条相等的对角线
// 边长不能为0,对角线长度应该是边长的√2倍(平方后是2倍)
return distances[0] > 0 &&
distances[0]
复杂度分析
| 复杂度类型 | 大小 | 说明 |
|---|---|---|
| 时间复杂度 | O(1) | 固定计算6个距离并排序,常数时间 |
| 空间复杂度 | O(1) | 使用固定大小的数组存储距离 |