二刷LeetCode--29. 两数相除(C++版本)核心较复杂

该文章探讨了一种优化整数除法的方法,通过处理负数和边界条件,以及在循环中每次尝试减少除数的倍数,来降低时间复杂度,防止在极端情况下出现超时或溢出问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本题首先容易想到的就是不断的使除数自增,通过计数器判断增加了多少次, 那么增加的次数就是想要的答案。

// class Solution {
// public:
//     int divide(int dividend, int divisor) {
//         // 首先处理一些特殊情况
//         // 如果被除数为1直接返回除数
//         if(divisor == 1)
//             return dividend;
//         // 最终的结果的正负应该由flag决定
//         bool flag = true;
//         // 当两个数字有一个为负的时候结果为负
//         if((dividend < 0 && divisor > 0) || (dividend > 0 && divisor < 0))
//             flag = false;
//         // 如果超出限制就要按照题目进行相应的处理
//         if (dividend == INT_MIN && divisor == -1)
//             return INT_MAX;
//         // 因为负数的范围比正数范围大,因此将正数全部变为负数进行计算
//         if(dividend > 0)
//             dividend = -dividend;
//         if(divisor > 0)
//             divisor = -divisor;
            
//         int ans = 0;
//         while(1) 
//         {
//             int a = dividend, b = divisor, cnt = 1;
//             // 现在a,b都是负数
//             if (a > b) 
//                 break;
//             // b < a && a < 2 * b的时候进行循环
//             while(a - b <= b) 
//             {
//                 cnt += cnt;
//                 b += b;
//             }
//             ans += cnt;
//             dividend -= b;
//         }
//         return flag ? ans : -ans;
//     }
// };

class Solution {
public:
    int divide(int dividend, int divisor) {
        // 如果除数为1的话直接返回被除数即可
        if(divisor == 1)
            return dividend;
        // 还需要一个最终用来决定正负的标记
        bool flag = false;
        // 只有两个数据同号的时候结果才为正
        if((dividend > 0 && divisor > 0) || (divisor < 0 && dividend < 0))
            flag = true;
        // 还需要处理超出范围的问题,即被除数是最小的数,而除数是-1
        // 因为负数的范围大,而正数的范围比负数的范围小1
        if(dividend == INT_MIN && divisor == -1)
            return INT_MAX;
        // 我们将数据全部转为负数进行计算因为负数的范围更大
        if(dividend > 0)
            dividend = -dividend;
        if(divisor > 0)
            divisor = -divisor;
        // 进行计算,我们可以通过不断的累加除数,
        // 看除数经过多少次累加会超过被除数,这样就可以算出最终的结果
        // int res = 0, cnt = 1;
        int res = 0;
        while(true)
        {
            // 为了方便标记,我们给除数被除数起别名
            int a = dividend, b = divisor, cnt = 1;
            // 因为这里是负数,因此我们考虑的时候需要在正数的基础上加上符号,也就是大小于号需要反向
            if(a > b)
                break;
            // 当没有加到被除数那么大的时候就一直相加,计数器与最终的结果直接相关
            while(a - b <= b)
            {
                cnt += cnt;
                b += b;
            }
            // 当b大于a的时候就可以退出循环
            res += cnt;
            // 更新除数,这里注意都是负数,因此更新实际上使用的是减法
            dividend -= b;
        }
        return flag ? res : -res;
    }
};

本题主要影响速度的地方就是while循环,如果我们使用传统的方式一次增加一个的话,时间复杂度是O(n),那么在数字比较极端的时候会导致超时情况的出现,因此就有了下图的优化情况。每次尝试减去除数的倍数,在减到导致被除数为负数的时候退出,更新被除数,然后将减去了多少个除数的计数器结果加入到最终结果中。下一轮继续这种减法,然后循环,直到被除数小于除数。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值