题目
Divide two integers without using multiplication, division and mod operator.
If it is overflow, return MAX_INT.
思路
这道题需要用到移位操作,这就涉及到一些二进制相关的概念,先普及一下:
1)二进制表示中,首位是符号位,1表示负数,0表示正数
2)二进制表示中,java的int是32位,取值范围为[-2^31,2^31-1]
3)移位分为左移和右移,左移<<就是在某个二进制数末位后补0;右移分为逻辑右移>>>和符号右移>>,逻辑右移在这个数的首位前补0,符号右移则在这个数的首位前补符号位
这道题有几个注意点:
1)divisor=0,返回2^31-1
2)处理溢出,当且仅当dividend=-2^31,divisor=-1,这时正确结果应该是2^31,但它超过了int的取值范围,只能返回2^31-1
3)最简单的思路是在dividend中每次减去divisor直到dividend<divisor,但是这样会超时。利用移位操作,divisor<<=1直到divisor>=dividend,这样每次减去的就是2的幂,时间复杂度可以降低到O(logN)
4)将int转化为long,在计算出正确结果后再转化为int
5)用表达式boolean isNegative = (((dividend^divisor)>>>31)==1) ? true : false判断结果正负(先亦或再逻辑右移31位),这样后面操作的dividend和divisor都是正数
代码
public class Solution {
public int divide(int dividend, int divisor) {
if(divisor == 0)
return Integer.MAX_VALUE;
if(dividend == Integer.MIN_VALUE && divisor == -1)
return Integer.MAX_VALUE;
long result = 0;
boolean isNegative = (((dividend^divisor)>>>31)==1) ? true : false;
long dividendL = Math.abs((long)dividend);
long divisorL = Math.abs((long)divisor);
int digit = 0;
while(divisorL << 1 <= dividendL){
divisorL <<= 1;
digit++;
}
while(digit >= 0){
if(dividendL >= divisorL){
dividendL -= divisorL;
result += 1<<digit;
}
divisorL >>= 1;
digit--;
}
return isNegative ? (int)(-result) : (int)result;
}
}