LintCode_两个整数相除

问题描述:

将两个整数相除,要求不使用乘法、除法和 mod 运算符。如果溢出,返回 2147483647 。

样例:给定被除数 = 100 ,除数 = 9,返回 11

算法思想:

方法一:(这是开始自己想出来的,算法思想简单,缺点是,循环次数多,运行速度慢

如果不能采用乘除运算方法,那么可以采用加减方式,当然还要(1)、注意分类:正正,正负,负正,负负;(2)、溢出问题;

    public static int divide(int dividend, int divisor) {

        if(divisor==0){
            return 2147483647;
        }
        
        if(dividend==0){
            return 0;
        }
        
        if(dividend==-2147483648&&divisor==-2147483648){
            return 1;
        }
        
        
        int result=0;
        
        //如果被除数为负数,除数为正数
        if(dividend<0&&divisor>0){
            //循环将除数加至被除数中,直至被除数大于或者等于0
            while((dividend+divisor)<=0){       
                dividend+=divisor;
                result--;
            }
        }else if(dividend>0&&divisor>0){
            //被除数与除数都是正数,直接计算,result++
            while((dividend-divisor)>=0){
                
                dividend-=divisor;
                result++;
            }
          
        }else if(dividend>0&&divisor<0){
            //被除数为正数,除数为负数,将除数转变成正数,result--
            while((dividend+divisor)>=0){
                dividend+=divisor;
                result--;
            }
        }else if(dividend<0&&divisor<0){
            while((dividend-divisor)<=0&&result<2147483647){
                //可能(-2147483648)/(-1)=2147483648,刚好导致溢出
                dividend=dividend-divisor;
                result++;
            }
        }
        return result;
    }
    

注: 此题在测试过程中,最纠结的就是碰到-2147483648等的溢出问题,例如被除数和除数都是-2147483648时,如果,在最开始没有使用
<pre name="code" class="java" style="color: rgb(113, 113, 113);">        if(dividend==-2147483648&&divisor==-2147483648){
            return 1;
        }
 
语句,result最终结果为 
2147483647。在负负情况下添加添加打印result和dividend的语句,可以看到result和dividend在while循环中的结果,很奇怪;如果被除数和除数是其他数据,运行结果正常。因此, 
这不是逻辑问题,而是溢出! 

方法二:百度了下别人的做法,发现可以使用位运算,减少循环步骤,大大减少了运算时间,在被除数很大,除数很小的时候很有优势。因为左移一位相当于数字乘2;所以有时左移右移运算配合加减法,就相当于乘除法;

    public static  int divide(int dividend, int divisor) {  
        // Write your code here  
        //判断dividend与divisor是否是同符号,同符号,结果为正,不同符号,结果为负数
        Boolean resultGreatThanZero = true;  
        if(dividend>0&&divisor<0||dividend<0&&divisor>0)  
            resultGreatThanZero = false;  
        //保存最终结果
        int ret = 0;
        //将d1与d2都转变成正数运算
        long d1 = abs((long)dividend);  
        long d2 = abs((long)divisor);  
        
        while(d1>=d2)  
        {  
            long temp = d2;  
            long cnt = 1;  
            while(d1>=temp)  
            {  
                d1-=temp;  
                ret+=cnt;
                //左移一位,相当于cnt乘2;
                //不能直接使用乘法运算,那么可以采用左移代表乘法,可以减少运算步骤
                cnt = cnt<<1;  
                temp = temp<<1;  
            }  
        }  
        if(!resultGreatThanZero)  
            ret*=-1;  
        //考虑到溢出
        if(ret<(long)INT_MIN||ret>(long)INT_MAX)  
            return (int) INT_MAX;  
        return (int) ret;  
    }  
    
    private static long abs(long divisor) {
    
        if(divisor<0){
            divisor=divisor*(-1);
        }
    return divisor;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值