补充一道题目:149. 直线上最多的点数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

同一直线上的点集相关问题,使用哈希表遍历的方法,外层循环选定一个点,从头到尾去遍历其余的点,查看有多少的点与给定点的直线斜率相同(我们知道,一个点和一个斜率可以确定一条直线),那么只需要在哈希表记录下内层循环遍历下同一斜率的点,最后加上定点就得到当前组合下的最大点数。

斜率一共对应五种情况
横纵坐标差值为0是特殊情况处理,直接给特定斜率

  1. 横坐标差值为0 (字符串“ 1/ 0” 表示)
  2. 纵坐标差值为0 (字符串“ 0 / 1 “表示)
  3. 横纵差值都为正 (斜率为正)
  4. 横纵差值都为负 (斜率为正)
  5. 横纵差值有一个为负一个为正 (斜率为负,并且-1 /2 和 1 / -2 都要统一为-1 /2 )

最终把斜率转换为字符串存储,先使用欧几里得算法来缩放差值diff_x和diff_y,得到一个最简斜率(需要为负数斜率加”-“)作为哈希表的key

class Solution {
public:
    int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
    int maxPoints(vector<vector<int>>& points) {
        if (points.size() == 1) {
            return 1;
        }
        int res = INT_MIN;

        for (int i = 0; i < points.size(); i++) {
            unordered_map<string, int> lineMap;
            int resV = INT_MIN;
            for (int j = i + 1; j < points.size(); j++) {
                int diff_x = points[i][0] - points[j][0];
                int diff_y = points[i][1] - points[j][1];
                
                int g = gcd(abs(diff_x), abs(diff_y));
                int shrink_x = 0;
                int shrink_y = 0;
                if(diff_x == 0){
                   shrink_x = 1;
                   shrink_y = 0;
                }else if(diff_y == 0){
                   shrink_x = 0;
                   shrink_y = 1;
                }else{
                   shrink_x = diff_x / g;
                   shrink_y = diff_y /g;
                }
                string lineRate = "";
                
                lineRate += to_string(abs(shrink_x));
                lineRate.push_back('_');
                lineRate += to_string(abs(shrink_y));

                 if(shrink_x < 0 && shrink_y > 0|| shrink_x > 0 && shrink_y < 0){
                   lineRate = "-"+lineRate;
                }

                lineMap[lineRate]++;

                resV = max(lineMap[lineRate], resV);
            }
            res = max(res, resV + 1);
        }
        return res;
    }
};

欧几里得算法:(递归写法,当一个参数为0时,自动返回另一个非零参数)

int gcd(int a,int b){
    return b == 0 ? a : gcd(b,a%b);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值