LeetCode:29.Divide Two Integers[Medium]

题目:Divide two integers without using multiplication, division and mod operator.If it is overflow, return MAX_INT.
首先,题目要求计算两个数相除的结果
其次,不能使用乘法、除法和模运算;如果结果溢出直接返回MAX_INT。

根据题目的限制,首先可能想到使用减法,循环用被除数减除数,知道小于0为止,但是这样对于很大的被除数肯定超时了(如2147483647除以1)。

可以使用移位运算,在Java中有三种移位运算

  • << : 左移运算符,num << 1,相当于num乘以2
  • >> : 右移运算符,num >> 1,相当于num除以2
  • >>> : 无符号右移,忽略符号位,空位都以0补齐
    注意运算符都在操作数的右侧

该题使用移位运算符的思路其实和使用减法相同,不过提高了效率(注意符号的处理,可以先保存符号位,然后将取两个数的绝对值计算):

  1. 每次将divisor左移shift位,得到最接近(小于)dividend的最大的数maxCloset,该数与divisor的商构成了最终商的一部分
  2. 使用dividend减去maxCloset后继续步骤1,直到dividend小于divisor

注意,对于可能出现的溢出,需要首先将操作数转换为long类型,同时程序中使用的数据类型尽量为long类型。最后类型转换前,也需要判断是否会溢出。

代码如下:

public class Solution {
    public int divide(int dividend, int divisor) {
        long dividendLong = dividend;
        long divisorLong = divisor;
        //可能的极端情况
        if(divisorLong == 0)
            return Integer.MAX_VALUE;
        if(dividendLong == 0)
            return 0;
        //保存结果商
        long trade = 0;
        int sign = 1;//计算符号位
        if((dividendLong < 0) ^ (divisorLong < 0))
            sign = -1;
        //取绝对值,如果使用int,这里可能出现溢出
        dividendLong = Math.abs(dividendLong);
        divisorLong = Math.abs(divisorLong);
        while(dividendLong >= divisorLong){
            int shift = 0;//左移位数
            long part = 1;//部分商
            while(divisorLong<<shift < dividendLong) {
                ++shift;
                part <<= 1;
            }
            if(dividendLong == divisorLong<< shift) {
            //如果相等,则直接跳出
                trade += part;
                break;
            }
            //不相等,需要向右移位,取maxCloset
            trade += part >> 1;
            dividendLong -= divisorLong << (shift-1);
        }
        //最后判断是否存在溢出
        if(trade*sign > Integer.MAX_VALUE || trade*sign < Integer.MIN_VALUE)
            return Integer.MAX_VALUE;
        else
            return (int)trade*sign;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值