Divide two integers without using multiplication, division and mod operator.
If it is overflow, return MAX_INT.
要求不使用乘法、除法或模運算實現: dividend/divisor,也就是隻能用加、減或位運算。int的取值範圍[-2147483648, 2147483647],即最小值的abs比最大值的abs大1,那麼,除法卻發生溢出的情況僅僅當:dividend=-2147483648,divisor=-1。此外要注意的是:Math.abs(-2147483648) = -2147483648,要避免這種情況public class Solution {
public int divide(int dividend, int divisor) {
if(divisor == 0) {
return Integer.MAX_VALUE;
}
int result = 0;
if(dividend == Integer.MIN_VALUE) {
if(divisor == -1) {
return Integer.MAX_VALUE;
}
dividend += Math.abs(divisor); //之所以這麼做是爲了避免下面對dividend求abs時發生溢出
result++; //經過上面一行的處理,此處result要記得加1
}
if(divisor == Integer.MIN_VALUE){ //當divisor爲MIN時,結果要麼爲1(dividend也爲MIN),要麼爲0
return result;
}
boolean isNeg = (dividend^divisor)>>>31 ==1; //用xor,並右移31位高位補0的方法來判斷結果的正負
//乘法可能會溢出,且題目不讓用,此外位運算效率高
dividend = Math.abs(dividend);
divisor = Math.abs(divisor); //經過上面的處理和判斷,此處的abs運算肯定不會溢出
//經過上面的處理,問題變成兩個正整數的除,且不會溢出
//思路是任一個數可以表示成以2的冪爲底的一組基的線性組合,num=a_0*2^0+a_1*2^1+a_2*2^2+...+a_n*2^n
//且位運算中,左移相當於*2,右移相當於/2
//先讓除數左移直到大於被除數之前得到一個最大的基,然後接下來每次嘗試減去這個基,
//如果可以則結果增加加2^k,然後基繼續右移迭代,直到基爲0爲止
int digit = 0; //標記移了多少位
while(divisor <= (dividend>>1)) {
divisor <<= 1;
digit++;
}
while(digit>=0) {
if(dividend >= divisor){
result += 1<<digit;
dividend -= divisor;
}
divisor >>= 1;
digit--;
}
return isNeg ? -result : result;
}
}