《leetCode》:Divide Two Integers

题目

Divide two integers without using multiplication, division and mod operator.

If it is overflow, return MAX_INT.

思路一:报超时错误

/*
完成两个数的除法,不能用乘法、除法、和求余运算
思路:由于有上面的限制,因此只能用加法和减法来做此题

*/
//函数中第一个参数为:被除数,第二个参数为:除数。
//例如:如24÷8=3,中24就为被除数,8为除数
/*
需要考虑的测试用例:
两个数同号
1)同为正号 16/4  、4/16
2)同为负号  -16/(-4),(-4)/(-16)
两个数为异号
1)(-16)/4,(-16)/32   分子为负数
2)16/(-4) ,16/(-32)

分子分母为零的情况。
如果除数是0,被除数是非零自然数时,商不存在.这是由于任何数乘0都不会得出非零自然数.
如果被除数、除数都等于0,在这种情况下,商不唯一,可以是任何数.这是由于任何数乘0都等于0.

虽然有这么的测试用例,可以这样转换,
将两个数都变成正数来解此题。
*/
int divide(int dividend, int divisor) {
    if(divisor==0&&dividend>0){
        return INT_MAX;
    }
    if(divisor==0&&dividend<0){
        return INT_MIN;
    }
    //这里将0/0=0来考虑。
    if(dividend==0){
        return 0;
    }
    int symbol_1=1;
    int symbol_2=1;
    //将两个数都变为正数
    if(dividend<0){
        symbol_1=-1;
        dividend=-dividend;
    }
    if(divisor<0){
        symbol_2=-1;
        divisor=-divisor;
    }
    if(divisor>dividend){//除数的绝对值大于被除数的绝对值
        return 0;
    }
    if(divisor==dividend){
        return symbol_1==symbol_2?1:-1;
    }
    //除数的绝对值小于等于被除数的绝对值
    if(divisor==1){
        return symbol_1==symbol_2?dividend:-dividend;
    }
    int diff=dividend-divisor;
    int result=1;
    while(diff>divisor){
        result++;
        diff=diff-divisor;
    }
    return symbol_1==symbol_2?result:-result;//符号相同输出为result,否则输出-result;


}

报超时错误,如下:

思路二

此种思路来源于
https://leetcode.com/discuss/43313/32-times-bit-shift-operation-in-c-with-o-1-solution
我刚开始也想到了要利用级数来进行求解,但是我不是讲结果展开为幂级数,而是将除数展开为幂级数,因此,写了下代码还是不行,还是报超时错误。
下面的思路确实很好,别人怎么这么聪明了,自己就是想不到,这应该就是差距吧。

具体思路如下:

we assure the factor ret's binary fomula is

ret = a0 + a1*2 + a2*2^2 + ...... + a29*2^29 + a30*2^30 + a31*2^31; ai = 0 or 1, i = 0......31

the dividend B and divisor A is non-negative, then

A(a0 + a1*2 + a2*2^2 + ...... + a29*2^29 + a30*2^30 + a31*2^31) = B; Eq1

(1) when Eq1 divided by 2^31, we can get A*a31 = B>>31; then a31 = (B>>31)/A;

if (B>>31) > A, then a31 = 1; else a31 = 0;

(2) when Eq1 divided by 2^30, we can get A*a30 + A*a30*2 = B>>30; then a30 = ((B>>30) - a30*A*2)/A; and (B>>30) - a31*A*2 can be rewritten by (B-a31*A<<31)>>30, so we make B' = B-a31*A<<31, the formula simplified to a30 = (B'>>30)/A

if (B'>>31) > A, then a30 = 1; else a30 = 0;

(3) in the same reason, we can get a29 = ((B-a31*A<<31-a30*A<<30)>>29)/A, we make B'' = B' - a30*A<<30, the formula simplified to a29 = (B''>>29)/A;

do the same bit operation 32 times, we can get a31 ..... a0, so we get the ret finally.

the C solution with constant time complexity

根据上面的思路实现的代码如下:


int divide(int dividend, int divisor) {
    if(divisor==0||(dividend==INT_MIN&&divisor==-1)){//这两种情况产生溢出
        return INT_MAX;
    }
    if(dividend==0){
        return 0;
    }
    bool flag=(dividend>0)^(divisor>0);//用来标识两个数的符号是否是相同的。,相同就为false。
    //将两个数都变为正数
   unsigned int  B=(dividend>0)?dividend:-dividend;
   unsigned int  A=(divisor>0)?divisor:-divisor;
    int result=0;
    for(int i=31;i>=0;i--){
        if((B>>i)>=A){
            result=(result<<1)|0x01;//移位之后在低位添加一个1
            //更新B
            B-=(A<<i);
        }
        else{
            result=(result<<1);
        }
    }


    return flag?-result:result;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值