携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第3天,点击查看活动详情
题目描述
给定一个二维坐标中的四个点的坐标,判断给出的四个点是否能够形成一个正方形;
例1:输入:"[6987,-473] [6985,-473] [6986,-472] [6986,-474]" 输出:"true"
例2:输入:"[0,0] [1,1] [1,0] [1,1]" 输出:"false"
本题值得注意的地方
- 所给出的四个点的坐标没有顺序
- 所给出的四个点的坐标有可能是重复的
- 坐标的数值范围-1e4 ~ 1e4
原题地址:593. 有效的正方形
解题思路
题目中所给的四个点有可能出现重复的点,这里为了方便,使用了 map 标记各点用来判断是否重复。
判断一个图形是否为正方形的方法有很多,这里选择用对角线是否相等且垂直的方法。若对角线相等但不垂直,那该图形一定不是正方形,例如图中2长方形或者等腰梯形等。若对角线只垂直不相等,那么该图形也一定不为正方形,例如图中3的菱形。
该题所给的参数为 4 个vector,且点的顺序是随机的,为了方便处理,我们应该先对四个点进行一个从左到右的排序。排序完成后,两个对角线即为点 0 与点 3 以及点 1 与点 2 所连成的线。在判断对角线是否垂直,只需要判断图中 1 的四个三角形其中之一为直角三角形即可。
实现代码
class Solution {
public:
bool validSquare(vector<int>& p1, vector<int>& p2, vector<int>& p3, vector<int>& p4) {
// 将p1 ~ p4放入一个vector中,方便排序与遍历
vector<vector<int>> p = {p1,p2,p3,p4};
// 利用map来检查输入的点有无重复
map<vector<int>,int> map;
for(int i = 0;i < 4;i++) if(++map[p[i]] > 1) return false;
// 按照各点的 x 坐标升序排序,当横坐标一样时,按照纵坐标升序排序
sort(p.begin(),p.end(),[](const auto &a,const auto &b){return a[0] == b[0]?a[1] < b[1]:a[0] < b[0];});
// 计算中心点的坐标
double x=(double)(p[3][0] + p[0][0]) / 2,y=(double)(p[2][1] + p[1][1]) / 2;
// 判断对角线是否相等,不相等则不是正方形
if((pow(p[3][0] - p[0][0],2) + pow(p[3][1] - p[0][1],2)) != (pow(p[2][0] - p[1][0],2) + pow(p[2][1] - p[1][1],2))) return false;
// 判断中心点与端点之间的连线是否垂直
if((pow(p[0][0] - x,2) + pow(p[0][1] - y,2))*2 != (pow(p[0][0] - p[1][0],2) + pow(p[0][1] - p[1][1],2))) return false;
return true;
}
};