问题描述
给定四个坐标点,判断是否能围成一个正方形。
总体思路
总共有四个点,遍历其中三个点(足够推出第四个角为90度,四个边相等),以这三个点为中心,计算与其它三个点的距离;那么这三个距离中必定有一个长度最大,另两个短的相等;再判断两个短边是否垂直,就可以判定为正方形。
解析
/*
如:points = { {0, 0}, {1, 1}, {1, 0}, {0, 1} }
每个点的下标: 0 1 2 3
从第一个点开始遍历,第一个点就会与其它三个点组合,有三组距离长度,将点和长度保存
第一次遍历
point_dis = {
{0, 1, 4}
{0, 2, 2}
{0, 3, 2}
}
删除最大长度的一行
point_dis = {
{0, 2, 2}
{0, 3, 2}
}
斜率积为-1 k1 * k2 = -1
k1 = ((points[point_dis[0][1]][1] - points[point_dis[0][0]][1]) / (points[point_dis[0][1]][0] - points[point_dis[0][0]][0]))
k2 = ((points[point_dis[1][1]][1] - points[point_dis[1][0]][1]) / (points[point_dis[1][1]][0] - points[point_dis[1][0]][0]));
points[point_dis[0][1]][1] 表示points中第一行第一列的数,因为point_dis[0][1] == 1
斜率不存在,无法通过除法算出斜率,转换为乘法
k1 = a / b; k2 = c / d; k1 * k2 = -1
ac = -bd
算出ac和bd
ac = (points[point_dis[0][1]][1] - points[point_dis[0][0]][1]) * (points[point_dis[1][1]][1] - points[point_dis[1][0]][1]);
bd = (points[point_dis[0][1]][0] - points[point_dis[0][0]][0]) * (points[point_dis[1][1]][0] - points[point_dis[1][0]][0]);
*/
代码
class Solution
{
public:
bool validSquare(vector<int>& p1, vector<int>& p2, vector<int>& p3, vector<int>& p4)
{
//如果四个点中有相同的点,就返回false
if (p1 == p2 || p1 == p3 || p1 == p4 || p2 == p3 || p2 == p4 || p3 == p4) return false;
//为方便查找和计算,将四个点放到二维数组中
vector<vector<int>> points = {p1, p2, p3, p4};
//将两个点的位置和两个点的距离放到二维数组中,该数组中已经确定前两列为两个点保存在points中为位置(行数)
vector<vector<int>> point_dis;
//两个点间的距离
vector<int> dis;
//只需遍历三个点
for (int i = 0; i < 3; ++i)
{
//该点与其他点的连线
for (int j = 0; j < 4; ++j)
{
//排除与自身的连线
if (i != j)
{
//将距离与两个点放到数组中
dis.push_back(i);
dis.push_back(j);
dis.push_back(pow(points[i][0] - points[j][0], 2) + pow(points[i][1] - points[j][1], 2));
point_dis.push_back(dis);
dis.clear();
}
}
//在point_dis的第2列中中找到最大和两个相等的小值,找到对应的前两个值(一条直线),判断两条直线是否垂直
//三组线的最大长度
int max_len = -1;
//三组线的最大长度的下标
int max_index = -1;
for (int k = 0; k < 3; ++k)
{
if (point_dis[k][2] > max_len)
{
max_len = point_dis[k][2];
max_index = k;
}
}
//找到最大长度,将其删除,方便操作
point_dis.erase(point_dis.begin() + max_index);
//删除后只剩下两行数据,比较长度是否相等
if (point_dis[0][2] != point_dis[1][2]) return false;
//斜率之积为-1,为方便计算斜率不存在的情况,转化为乘法
int slope1 = (points[point_dis[0][1]][1] - points[point_dis[0][0]][1]) * (points[point_dis[1][1]][1] - points[point_dis[1][0]][1]);
int slope2 = (points[point_dis[0][1]][0] - points[point_dis[0][0]][0]) * (points[point_dis[1][1]][0] - points[point_dis[1][0]][0]);
//判断垂直
if (slope1 != 0 - slope2) return false;
//数据清零
point_dis.clear();
}
return true;
}
};