[leetcode149],直线上最多的点数与unordered_map实例化报错的问题

[leetcode149],直线上最多的点数

问题来源

https://leetcode-cn.com/problems/max-points-on-a-line/

在这里插入图片描述

atan2函数

在做之前,先解释一下C语言math.h库中的atan2函数,他的作用就是求出以弧度表示的一个点相对与原点的反正切值,取值范围为: ( − π , π ] (-\pi,\pi] (π,π],不包括 − π -\pi π

 double atan2(double y, double x) 

在此基础上,对参数动一下手脚,就可以得到任意的两个点之间以弧度表示的反正切值
r e s = y − 0 x − 0 res=\frac{y - 0}{x-0} res=x0y0
⇒ r e s = y x \Rightarrow res=\frac{y}{x} res=xy

弧度的计算公式为: 角 度 数 × ( π / 180 ° ) 角度数\times(π /180°) ×π/180°

那么,如果我们想求出任意两个点的弧度,在传参的过程中,传入相对于一个点偏移就可以了

atan2(y1 - y,x1 - x);

那么,所求的结果为 ( x 1 , y 1 ) (x1,y1) (x1,y1)点相对于 ( x , y ) (x,y) (x,y)点的弧度的反正切值

根据弧度求角度

a t a n 2 ( ) atan2() atan2()函数的返回值, × 180 / π \times 180/\pi ×180/π,这里的 π \pi π可以使用我们自定义的宏来代替,以前经常背诵的圆周率用上了。。。

#define PI 3.1415926535

在这里插入图片描述

未通过的解法

很遗憾,leetcode在最后的结果中卡了库函数的精度,所以使用atan2()库函数求解是不对的

  • [[0,0],[94911150,94911151],[94911151,94911152]]
  • [[0,0],[94911151,94911150],[94911152,94911151]]

打表的两个用例,大家乐呵一下就可以了

class Solution {
public:
    int maxPoints(vector<vector<int>>& points) {
        int n = points.size();
        if(n < 2)   return n;
        //if(n == 3 && points[0][0] == 0 && points[1][0] == 94911150 && points[2][0] == 94911151) return 2;
        //if(n == 3 && points[0][0] == 0 && points[1][0] == 94911151 && points[2][0] == 94911152) return 2;
        int res = 0;
        for(int j = 0; j < n; j++) {
#define PI 3.1415926535 
            unordered_map<double,int> mp;
            int same = 1;   // 相同点的数量
            for(int i = 0; i < n; i++) {
                if(i == j) continue;
                if(points[i][1] == points[j][1] && points[i][0] == points[j][0]) {
                    same++;
                    continue;
                }

                double t = atan2(points[i][1] - points[j][1],points[i][0] - points[j][0]);
                t = t + 360;
                //cout << t << " ";
                mp[t]++;
            }
            //cout << same << "-";
            //puts("");
            
            for(auto& e : mp) {
                int x = e.first, y = e.second;
                if(mp.count(x + 180)) y += mp[x+180];
                res = max(res,y + same);
                //cout << res << " ";
            }
            //puts("");
            res = max(res,same);
        }

        return res;
    }
};

ac程序

程序使用斜率来进行解决,但是首先要统计每个点出现的次数,因为会出现重复的点

注意,统计点出现的次数时,不可使用unordered_map哈希表

在这里插入图片描述
可以看出,报出的错误时,unordered_map隐式的删除了默认构造函数。

在这里插入图片描述
因为我们所传入的第一个键值key的类型是一个pair<int,int>类型,在初始化的时候,不能得到一个unordered_map的实例,因为pair<int,int>没有默认构造函数,在实例化pair的对象时,一定要存在初值,所以使用unordered_map会报错
在这里插入图片描述
另外,如果我们非得使用哈希表的话,可以考虑自定义一个pair,然后重写默认构造函数,让unordered_map可以无参进行实例化就可

class Solution {
public:
    typedef pair<int,int> PII;
    typedef long long LL;
    int maxPoints(vector<vector<int>>& points) {
        int n = points.size();
        if(n < 2) return n;
        map<PII,int> mp;  // 统计每个点出现的次数
        for(auto& e : points) mp[{e[0],e[1]}] ++;

        vector<pair<PII,int> > vec; // 记录每个点出现的次数
        for(auto& e : mp) vec.push_back(e);
        n = vec.size();
        if(n == 1) return vec[0].second;    // 排除只存在一个点的情况

        int res = 0;
        for(int i = 0; i < n; i++)
            for(int j = i + 1; j < n; j++) {
                // 记录 i j 的斜率
                LL x = vec[j].first.first - vec[i].first.first;
                LL y = vec[j].first.second - vec[i].first.second;
                int cur = vec[i].second + vec[j].second;    // 当前直线中点的数量

                // 统计后面的点
                for(int k = j + 1; k < n; k++) {
                    LL tx = vec[k].first.first - vec[i].first.first;
                    LL ty = vec[k].first.second - vec[i].first.second;
                    if(tx * y == ty * x) cur += vec[k].second;
                }

                res = max(res,cur);
            }
        return res;
    }
};
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值