LeetCode:29.Divide Two Integers[Medium]

来源:互联网 发布:1060剑灵优化 编辑:程序博客网 时间:2024/06/05 11:22

题目: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
原创粉丝点击