力扣593

问题描述

给定四个坐标点,判断是否能围成一个正方形。

总体思路

总共有四个点,遍历其中三个点(足够推出第四个角为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;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值