【LeetCode】29.Divide Two Integers 整数除法的实现

一、概述

输入两个数a和b,输出a/b,去尾法保留整数。不许用乘或除或取余。

想半天不知道怎么做。只好去看discuss。原来是用了左移和右移。

然后自己做。铁孤儿题。边界条件一堆,快把我折磨出INT_MIN的PTSD了。

二、分析

1、我的代码

先考虑一下算法:

现在有a和b,不让用除号怎么除呢?我们有不用除号的除法啊,同样的,有不用乘号的乘法。这就是左移或右移。左移除二,右移乘二。我想到了这步,但是之后就卡住了。还是蠢。

实际上的算法应该是对b操作:

b*2,判断a和b的大小,要是a>b,继续乘2直到a<b。若a<b,b左移,记下这时左移的次数c,求出2^c。

然后a-b,赋值给a。直到最后a<b。

举例为28/4。

首先28>4,4*2=8;28>8,8*2=16;28>16,16*2=32;28<32,32/2=16。

从4到16,左移2次,2^2=4。

然后28-16=12。

12>4,4*2=8;12>8,8*2=16;12<16,16/2=8。

从4到8,左移1次,2^1=2。

然后12-8=4。

4=4,4*2=8;8>4,8/2=4。

从4到4,左移0次。2^0=1。

然后4-4=0。

0<4,退出。

4+2+1=7。结果为7。

简而言之,就是把a分解成b*2^x+b*2^y+......

最后的结果就是2^x+2^y+......

代码如下:

class Solution {
public:
    int divide(int dividend, int divisor) {
        long result=0;
        int ex=0;
        int sign=0;
        if((dividend>0&&divisor>0)||(dividend<0&&divisor<0))
            sign=0;
        else
            sign=1;
        long _dividend;
        if(dividend==INT_MIN)
            _dividend=2147483648;
        else
            _dividend=abs(dividend);
        long _divisor;
        if(divisor==INT_MIN)
            _divisor=2147483648;
        else
            _divisor=abs(divisor);
        long tmp=_divisor;
        while(_dividend>=_divisor)
        {
            if(tmp<=_dividend)
            {
                tmp=tmp<<1;
                ex++;
            }
            else
            {
                tmp=tmp>>1;
                ex--;
                _dividend=_dividend-tmp;
                tmp=_divisor;
                result+=pow(2,ex);
                ex=0;
            } 
        }
        if(result==2147483648&&sign==1)
            return INT_MIN;
        if(result>INT_MAX||result<INT_MIN)
            return INT_MAX;
        if(sign==0)
            return result;
        else
            return -result;
    }
};

关键就是判断是否溢出。这个情况太多了。

INT_MIN和1不溢出,和-1溢出。

但是我又是直接abs算的,abs(INT_MIN)会报错,因此只能直接赋值。

麻烦死了。

2、较好的方法

算法一样,看看人家怎么处理边界条件。

class Solution {
public:
    int divide(int dividend, int divisor) {
        if (dividend == INT_MIN && divisor == -1) {
            return INT_MAX;
        }
        long dvd = labs(dividend), dvs = labs(divisor), ans = 0;
        int sign = dividend > 0 ^ divisor > 0 ? -1 : 1;
        while (dvd >= dvs) {
            long temp = dvs, m = 1;
            while (temp << 1 <= dvd) {
                temp <<= 1;
                m <<= 1;
            }
            dvd -= temp;
            ans += m;
        }
        return sign * ans;
    }
};

emmmm没比我好哪去,唯一的优点就是用了labs比我的abs好一些。

三、总结

辣鸡题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值