【算法】LeetCode第6076题,如何确定用int还是long long及不要对浮点数进行【等于比较】

6 篇文章 0 订阅

在这里插入图片描述
这是LeetCode周赛的一道题目,难度是中等。思路很简单,细节容易出错。

思路

只要不断比较斜率,出现新的斜率,线段数就加1。

细节1

class Solution {
public:
    int minimumLines(vector<vector<int>>& pri) {
        int n = pri.size();
        sort (pri.begin(), pri.end());
        if (n == 1) return 0;
        double refer_k = (pri[1][1] - pri[0][1])*1.0  / (pri[1][0] - pri[0][0]);
        int ans = 1;
        for (int i = 2; i < n; ++i) {
            double k = (pri[i][1] - pri[i-1][1])*1.0  / (pri[i][0] - pri[i-1][0]);
            if (k == refer_k) continue;
            refer_k = k;
            ans++;
        }
        return ans;
        
    }
}; 

这是我第一次提交的代码,使用了除法版本的斜率。显示通过了77个测试样例,死活不知道最后2个为什么不行?最后翻了讨论区,发现是浮点数的比较问题。
在这里插入图片描述
浮点数并非真正意义上的实数,在内存中存储的是近似数,所以用【==】去进行相等比较,出现的结果是很难预测的。解决办法有如下两个。

1.某种精度范围内的相等

可以设置精度为0.01, 如果fabs(a-b) <= 0.01,那么认为a和b是相等的。

2.转换成其他等式规避除法计算

我们可以将斜率的相等转换成乘法形式,这样就规避了除法产生的浮点数精度问题。
在这里插入图片描述
我们利用pair数据类型来记录斜率的分子和分母,用vector也行。先记录第一个线段的斜率,然后去求解后面线段的斜率。

class Solution {
public:
    int minimumLines(vector<vector<int>>& pri) {
        int n = pri.size();
        sort (pri.begin(), pri.end(), [](const vector<int>& a, const vector<int>& b){return a[0] < b[0];});

        if (n == 1) return 0;

        pair<int, int> k = {pri[1][1] - pri[0][1], pri[1][0] - pri[0][0]};
        int ans = 1;

        for (int i = 2; i < n; ++i) {    
            pair<int, int> t = {pri[i][1] - pri[i-1][1], pri[i][0] - pri[i-1][0]};
            if (k.first * t.second != k.second * t.first) {
                k = t;
                ans++;
            }
                      
        }

        return ans;
        
    }

细节2

在这里插入图片描述

第二个细节是数据的表示范围。看到题目的要求,初步的想法是每个数都是在10的9次方以内,所以它们相减的数据也是在10的9次方以内。而int的数据范围是2*10的九次方以内,相减后的数据是不会超过int类型的。所以上述pair类型用的是int,但是提交后发现会报错。报错信息指出,两个int数相乘超过了int的表示范围,也就是下图if语句内部的相乘语句。
在这里插入图片描述

if (k.first * t.second != k.second * t.first)

两个int变量相乘,会构造一个新的临时变量int,然后将结果赋值给这个临时变量。两个比较大的int数值相乘导致了溢出。所以我们的pair类型不能是int。可以将两个pair类型都改为long long,也可以单独修改一处地方,因为只要表达式中存在一个long long 类型,临时变量的类型就是long long类型。

class Solution {
public:
    int minimumLines(vector<vector<int>>& pri) {
        int n = pri.size();
        sort (pri.begin(), pri.end(), [](const vector<int>& a, const vector<int>& b){return a[0] < b[0];});

        if (n == 1) return 0;

        pair<long long, long long> k = {pri[1][1] - pri[0][1], pri[1][0] - pri[0][0]};
        int ans = 1;

        for (int i = 2; i < n; ++i) {    
            pair<int, int> t = {pri[i][1] - pri[i-1][1], pri[i][0] - pri[i-1][0]};
            if (k.first * t.second != k.second * t.first) {
                k = t;
                ans++;
            }
                      
        }

        return ans;
        
    }

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值