• 29. 两数相除


    题目:

      给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。

      返回被除数 dividend 除以除数 divisor 得到的商。

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

    示例 1:

    输入: dividend = 10, divisor = 3
    输出: 3
    解释: 10/3 = truncate(3.33333..) = truncate(3) = 3


    示例 2:

    输入: dividend = 7, divisor = -3
    输出: -2
    解释: 7/-3 = truncate(-2.33333..) = -2
     

    提示:

      被除数和除数均为 32 位有符号整数。
      除数不为 0。
      假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−2^31,  2^31 − 1]。本题中,如果除法结果溢出,则返回 2^31 − 1。

    解答:

      看了标签为二分法,没有思路,直接看解答:

      题目分类提示了二分查找,那么按二分查找的思路去想就行了,既然要求不能使用乘除模运算,那么就让除数不断自加倍增,与被除数对比,倍增过头了就初始化为原始的除数值再次循环倍增,循环过程中被除数减去除数不断减小,直到小于除数为止,其过程就是把二分查找中的 mid = (left + right) / 2 替换成了divisor * 2,把 left 和 right 替换成了 divisor_tmp 和 divideng_tmp,这样理解就比较直观了。

    //传进div的值必须是正整数,但是INT_MIN取绝对值会产生溢出问题,所以必须对它采取一定的措施,
    //即先让它减一次除数或者加一次除数(主要取决于除数的正负号),然后作为被除数的INT_MIN就不会产生溢出问题了。
    int divSub(int dividend, int divisor)
    {
        if (divisor>dividend) return 0;
        int res = 1;
        int original_divisor = divisor;
    
        while (dividend - divisor >= divisor)//特别需要注意的地方是dividend-divisor之后还大于等于divisor,即是dividend>=2divisor
        {
            divisor += divisor;
            res += res;//记录被除数是除数的多少倍
        }
        res += divSub(dividend - divisor, original_divisor);
        return res;
    
    }
    int divide(int dividend, int divisor) 
    {
        int res = 0;
        int flag = ((dividend>0 && divisor>0) || (dividend<0 && divisor<0));
        //先处理特殊值,即是处理边界溢出问题  INT_MIN
        if (divisor == 1)  return dividend;
        if (divisor == INT_MIN)    return dividend == INT_MIN ? 1 : 0;
        if (divisor == -1) return  dividend == INT_MIN ? INT_MAX : -dividend;
        if (dividend == INT_MIN)//如果被除数是32位最小整数必须进行一定的处理,先让其减或者加一次除数
        {
            dividend = (flag) ? (dividend - divisor) : (dividend + divisor);
            res++;
        }
        dividend = (dividend>0) ? dividend : -dividend;
        divisor = (divisor>0) ? divisor : -divisor;
        res += divSub(dividend, divisor);
    
        return  (flag) ? res : -res;
    }

      根据上面的思路,自己写了代码,并测试通过:

    int divideSub(int dividend, int divisor)
    {
        if (divisor > dividend)
            return 0;
    
        int res = 1;
        int originalDiv = divisor;
        while (dividend - divisor >= divisor)
        {
            divisor += divisor;
            res += res;
        }
    
        res += divideSub(dividend-divisor, originalDiv);
    
        return res;
    }
    
    int divide2(int dividend, int divisor) 
    {
        if (dividend == 0)
            return 0;
    
        //处理特殊情况
        if (divisor == 1)
            return dividend;
        else if (divisor == -1)
        {
            if (dividend == INT_MIN)
            {
                return INT_MAX;
            }
            return -dividend;
        }
        else if (divisor == INT_MIN)
        {
            if (dividend == INT_MIN)
                return 1;
            //INT_MIN的值较大,如果被除数是其他值,不够除,则直接返回0
            return 0;
        }
    
        //两个参数是否同符号
        bool sameSymbol = (dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0);
        int res = 0;
        if (dividend == INT_MIN)    //下面递归时,传入的都是正数,INT_MIN传入会溢出,先减或者加上一个除数
        {
            if (sameSymbol)
                dividend -= divisor;
            else
                dividend += divisor;
            res++;
        }
    
        if (dividend < 0)
            dividend = -dividend;
        if (divisor < 0)
            divisor = -divisor;
    
        res += divideSub(dividend, divisor);
        if (sameSymbol)
            return res;
        return -res;
    }
  • 相关阅读:
    第七章之main函数和启动例程
    第一章之系统调用、库函数、内核函数区别
    unp第七章补充之socket tcp 产生 rst响应的情况
    unp第七章补充之TCP半开连接与半闭连接
    Qt 布局管理器
    Qt setMargin()和setSpacing() 的含义
    工作感悟
    关于数组数据常用的技巧
    正则表达式练习
    call/apply应用-对象使用原型链上的方法
  • 原文地址:https://www.cnblogs.com/zyk1113/p/14009504.html
Copyright © 2020-2023  润新知