Divide two integers without using multiplication, division and mod operator.
If it is overflow, return MAX_INT.
Solution
The goal is to perform division without using multiplication, division or mod operator.
The most straightforward way to subtract dividend with divisor n times to return the divide is clearly not gonna work and will results in TLE.
We have to use bit manipulations
.
Suppose we want to divide 15
by 3
, so 15
is dividend
and 3
is divisor
.
[1] We subtract 3 from 15 and we get 12, which is positive.
[2] Shift 3 to the left by 1 bit and we get 6. Subtracting 6 from 15 still gives a positive result.
[3] Shift again and we get 12. We subtract 12 from 15 and it is still positive.
[4] Shift again, obtaining 24 and we know we can at most subtract 12.
Since 12 is obtained by shifting 3 to left twice, we know it is 4 times of 3. How do we obtain this 4? Well, we start from 1 and shift it to left twice at the same time.
And we implement this algorithm by using recursion to make code more efficient and makes more sense.
What is more, we have to consider the overflow situation. When the input contains Integer.MAX/MIN_VALUE
, the algorithm should be able to handle this number. To achieve which, we convert numbers into long
instead of int
, and in this way, not only can we solve the problem when input is around Integer.MAX_VALUE, we have also deal with the situation when the input is
2147483648
2
and the divisor shift to the left may be overflow, by converting everything into long, we can avoid this problem.
The code is shown as below.
Java
public class Solution {
public int divide(int dividend, int divisor) {
//Special Situation & Deal With Sign
if (divisor == 0 || (dividend == Integer.MIN_VALUE && divisor == -1))
return Integer.MAX_VALUE;
int sign = ((dividend<0 && divisor>0) || (dividend>0 && divisor<0)) ? -1 : 1;
//Initialization
long divide = 0;
long divisor_abs = Math.abs((long)divisor),dividend_abs = Math.abs((long)dividend);
divide = subdivide(dividend_abs,divisor_abs);
return sign == 1 ? (int)divide:(int)(-divide);
}
//Recursion
public long subdivide(long dividend_abs, long divisor_abs){
if(dividend_abs < divisor_abs)
return 0;
int times = 1,divide = 0;
long divisor_temp = divisor_abs;
while(dividend_abs >= (divisor_temp<<1)){
divisor_temp <<= 1;
times <<= 1;
}
dividend_abs -= divisor_temp;
divide += times;
return divide + subdivide(dividend_abs,divisor_abs);
}
}