编程训练第八期——两数相除

该博客介绍了如何在编程中不使用乘法、除法和mod运算符来计算两个整数的除法。核心解法是通过倍增和递归的方式,利用二分思想求解商,确保了在O(logN)的时间复杂度内完成计算。在处理过程中,注意了负数和溢出的情况,并给出了详细的代码实现。
摘要由CSDN通过智能技术生成

编程问题:

给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。返回被除数 dividend 除以除数 divisor 得到的商。

整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2


示例:

  • 输入: dividend = 10, divisor = 3
    输出: 3
    解释: 10/3 = truncate(3.33333…) = truncate(3) = 3
  • 输入: dividend = 7, divisor = -3
    输出: -2
    解释: 7/-3 = truncate(-2.33333…) = -2

解法:

1.倍增+递归
       本题的精髓在于递归使用div函数进行商的求解。 首先,若除数大于被除数,则商起码是1;接着考虑商是否为2:考虑商是否为2,只需将原来的除数翻个倍,与被除数比较大小;倘若被除数比除数的两倍还多,则考虑继续增加商的值,这时不考虑商是否再线性增加——因为速度太慢,而是以指数级增加除数,即将除数再翻一个倍,如此循环下去… 当出现被除数小于除数时,可以感性地理解为2倍的除数过大,大过被除数,所以需要退一步,被除数减掉一倍的除数,让这个差值(可看成是近似二分后,较小的那一部分)与题目所给的最初始的除数进行div函数的计算,重复上述操作,直到在若干次二分后剩余的一部分小于除数,返回零,意味着递归的结束。将每一层函数计算所得的值相加,就得到了最终结果。这实际上就是二分法的思想。
时间复杂度O(log N)
空间复杂度O(1)

class Solution {
private:
    int div(int a, int b)    // a < 0     b < 0
    {
        if(a > b) return 0;  // 递归退出条件    
        long count = 1;
        long tb = b;
        while(tb + tb >= a && tb + tb < 0){ // 当 -1073741824-1073741824 = 0 到-1073741824为止
            tb += tb;
            count += count;
        }
        return count + div(a-tb, b);
    }
public:
    int divide(int dividend, int divisor)
    { 
        if(divisor == -1 && dividend == INT_MIN) return INT_MAX; // 溢出判断
        int sign = 1;     //商为正
        if((dividend > 0 && divisor < 0)||(dividend < 0 && divisor > 0))
            sign = -1;    //商为负
        //将被除数和除数设置为负数可以避免溢出 这里避免溢出体现在div函数中 tb + tb < 0 这个退出循环条件
        int dividend_neg = dividend>0 ? -dividend : dividend;
        int divisor_neg = divisor>0 ? -divisor : divisor;
        if(dividend_neg > divisor_neg) return 0;
        long res = div(dividend_neg, divisor_neg);
        return sign == -1 ? -res : res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值