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;
}
原文地址:https://www.cnblogs.com/zyk1113/p/14009504.html