LeetCode第 29 题:两数相除(C++)

29. 两数相除 - 力扣(LeetCode)

LeetCode第 29 题:两数相除(C++)_第1张图片

要求不使用乘法、除法和 mod 运算符,但是乘法、除法、mod都是可以使用加减进行模拟的,假设输入分别为15、3,res表示结果:

  • 15 > 3: res置为1(代表结果至少为1),3 += 3(翻倍)得到6
  • 15 > 6: 比翻倍之后的数还要大,res置为2(1 += 1),6 += 6得到12
  • 15 > 12: res置为4,12 += 12得到24
  • 15 < 24,循环终止,此时的res为4,代表15里面至少有4个3,但是还没有结束,15里面还有剩余的数,也就是(15-12 = 3)
  • 用剩余部分3,和被除数3再次重回第一步
  • 当除数 < 被除数的时候,直接返回0
class Solution {
public:
    int divide(int dividend, int divisor) {
        //if(dividend == 0 || divisor == 1)    return dividend;
        //if(divisor == -1)   return dividend == INT_MIN ? INT_MAX : -dividend;
        int sign = (dividend>0) ^ (divisor>0) ? -1 : 1; //运算结果的正负
        long res = div(abs(dividend), abs(divisor));//参数传入绝对值
        if(sign == 1)   return res > INT_MAX ?    INT_MAX : res;
        return -res;
    }
    long div(long a, long b){//long防止溢出
        if(a < b)   return 0;
        long cnt = 1, val = b;
        while(val + val <= a){
            cnt += cnt;
            val += val;
        }
        return cnt + div(a-val, b);
    }
};

如果不使用long类型,那就可以转化为负数来防止溢出:

class Solution {
public:
    int divide(int dividend, int divisor) {
        if(dividend == 0 || divisor == 1)    return dividend;
        if(divisor == -1)   return dividend == INT_MIN ? INT_MAX : -dividend;
        int sign = (dividend>0) ^ (divisor>0) ? -1 : 1; //运算结果的正负
        int res = div(-abs(dividend), -abs(divisor));//参数传入绝对值的负值
        return sign == 1 ? res : -res;
    }
    int div(int a, int b){
        if(a > b)   return 0;//因为转为负号,这儿大小关系就反过来了
        int cnt = 1, val = b;
        while(val-a+val >= 0){//这样写是防止溢出
            cnt <<= 1;
            val += val;
        }
        return cnt + div(a-val, b);
    }
};

你可能感兴趣的:(leetcode)