Divide Two Integer - LeetCode

144/5= 28,不能用除号、乘号和取余的符号。


分析:

Brute Force: 用被除数减去除数,减几次结果就是几。

位运算:减法不够快,试探性的乘2来加快速度。

28是可以用二进制表示的 28 = 2^4+2^3+2^2

所以 144 = 5*(2^4)+5*(2^3)+5*(2^2), 也就是把5依次<< 4,3,2位 = 80,40,20

144-80-40-20 = 4 

所以关键是找到80这个位置,也就是5向左shift4位


思路:

1)判断符号

2)处理特殊情况  

dividend = 0 => 0

divisor = 0   => INT_MAX

divisor = 1;=> dividend

dividend = INT_MIN, divisor = -1  => overflow

divident = INT_MIN => 要把他处理成不越界的情况!因为后面要取绝对值。


3)然后开始计算,正数的情况。

记录位数,何时divisor再乘以2就超过dividend的一半了 , 也就是5*2*2*2*2=80的时候超过了144/2=72. 位数=4。

利用调整这个位数来累加结果。

注意!只有剩下的dividend还大于current divisor的时候才做减法。否则就一直等着,等到current divisor降下来。

比如144-80-40-20 = 4,此时要等待current divisor=10,5。 发现都不行再跳出。

4)返回结果:

因为不能用乘法所以不可以是res*sign。想要取负可以用(~res+1)。



时间复杂度:

BF: O(n)

位运算: 由于是考察以2为基底的数的计算。又是用位操作实现的。所以是O(logn)



Code (C++):

class Solution {
public:
    int divide(int dividend, int divisor) {
        if(divisor == 0) return INT_MAX;
        if(divisor == 1) return dividend;
        if(dividend == 0) return 0;
        int res = 0;
        int sign = 1;
        if(dividend == INT_MIN)
        {
            if(divisor == -1) return INT_MAX;
            dividend += abs(divisor);
            <strong>res++; </strong>//因为最后res是按照正数算出来的。在最后return的时候才翻转过来!
        }
        if(divisor == INT_MIN) return res;
        if((divisor < 0 && dividend > 0) || (divisor > 0 && dividend < 0)) sign = -1;
        dividend = abs(dividend);
        divisor = abs(divisor);
        int tmp = divisor;
        int digit = 0;
        while((dividend >> 1) >= tmp)
        {
            digit++;
            tmp = tmp<<1;
        }
        while(digit >= 0)
        {
            <strong>if(dividend >= tmp)</strong>
            {
                dividend = dividend - tmp;
                res += 1<<digit;
                
            }
            tmp = tmp>>1;
            digit--;
        }
        return sign == 1 ? <gs id="7c0030bc-5605-466b-bf77-10bdb9697f10" ginger_software_uiphraseguid="67fc0744-2e5c-4357-ba53-5515ba2941d2" class="GINGER_SOFTWARE_mark">res</gs><gs id="4799052b-7386-4652-a82c-de7b11dd733c" ginger_software_uiphraseguid="67fc0744-2e5c-4357-ba53-5515ba2941d2" class="GINGER_SOFTWARE_mark"> :</gs> (~res+1);
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值