Problem
Given two integers dividend
and divisor
, divide two integers without using multiplication, division, and mod operator.
The integer division should truncate toward zero, which means losing its fractional part. For example, 8.345
would be truncated to 8
, and -2.7335
would be truncated to -2
.
Return the quotient after dividing dividend
by divisor
.
Note: Assume we are dealing with an environment that could only store integers within the 32-bit signed integer range: [−2^31, 2^31 − 1]
. For this problem, if the quotient is strictly greater than 2^31 - 1
, then return 2^31 - 1
, and if the quotient is strictly less than -2^31
, then return -2^31
.
Examples
Example 1:
Input:
dividend = 10, divisor = 3
Output:
3
Explanation: 10/3 = 3.33333.. which is truncated to 3.
Example 2:
Input:
dividend = 7, divisor = -3
Output:
-2
Explanation: 7/-3 = -2.33333.. which is truncated to -2.
Solution
Method 1 - Using Binary Shifts
We know:
dividend = (quotient) * divisor + remainder
We need to find the quotient given the divisor and dividend.
Any number can be represented in binary form:
num = a_0*2^0 + a_1*2^1 + a_2*2^2 + ... + a_n*2^n
Same goes for quotient
. Let us have an example: 58/5
:
58 = (11) * 5 + 3
In binary, this quotient is ( $(11)_{10} = (1011)_2$ ):
58 = (2^3 + 2^1 + 2^0) * 5 + 3 // --- (I)
58 = [(2^3 * 5) + (2^1 * 5) + (2^0 * 5)] + 3 // --- (II)
We are given the equation 58 = q * 5 + rem
and need to find q
.
First, multiply 5 by powers of 2 until the result exceeds the dividend. Since multiplication operator is not allowed, we use bitwise left shift for multiplication:
5 << 0 = 5 // less than dividend
5 << 1 = 10 // less than dividend
5 << 2 = 20 // less than dividend
5 << 3 = 40 // less than dividend
5 << 4 = 5*2*2*2*2 = 80 // exceeds divided, so stop and consider previous value
We observe that:
58 = (2^3 * 5) + (something * 5) + rem // --- (III)
You can see we are getting close to the equation we initialy wanted (eqa II).
Since 5 is multiplied by (2^3), we add (2^3) to our answer and update the dividend:
58 - (2^3 * 5) = 18 = something * 5 + rem
Further operating on equation III:
58 - (2^3 * 5) = (something * 5) + rem
58 - (8 * 5) = something * 5 + rem
58 - 40 = something * 5 + rem
18 = something * 5 + rem
What we effectively have done is, subtracted the result we got from our first step from dividend (58 - 40)
.
We arived at the same question again but with a smaller dividend this time.
dividend = 18, divisor = 5
Therefore let us repeat the process:
5 << 0 = 5 // less than dividend
5 << 1 = 5*2 = 10 // less than dividend
5 << 2 = 5*2*2 = 20 // exceeds divided, so stop and consider previous value
We add 2^1 to our answer. Looking back:
18 = (2^1 * 5) + (something * 5) + rem
58 - (2^3 * 5) = (2^1 * 5) + (something * 5) + rem
58 = (2^3 * 5) + (2^1 * 5) + (something * 5) + rem
You can notice we are gradually advancing towards equ II: Our new dividend is now:
18 - (2^1 * 5) = (something * 5) + rem
18 - (2 * 5) = something * 5 + rem
18 - 10 = something * 5 + rem
8 = something * 5 + rem
dividend = 8, divisor = 5
Repeating the process:
5 << 0 = 5 // less than dividend
5 << 1 = 5*2 = 10 // exceeds divided, so stop and consider previous value
We add 2^0 to our answer. New dividend:
8 = (2^0 * 5) + (something * 5) + rem
8 - 5 = something * 5 + rem
3 = something * 5 + rem
dividend = 3, divisor = 5
At this step, we stop iterating as our dividend is less than the divisor (we have also found our remainder = 3, as 5 should be multiplied with 0 and what remains is the remainder).
Looking back again for the last time:
3 = 0*5 + rem
8 = (2^0 * 5) + 3
18 = (2^0 * 5) + (2^1 * 5) + 3
58 = (2^3 * 5) + (2^1 * 5) + (2^0 * 5) + 3
In the process, we have finally reached the equation we wanted to, and have got the answer as:
quotient = (2^3 + 2^1 + 2^0)
Code
Java
public int divide(int dividend, int divisor) {
//handle special cases
if (divisor == 0) return Integer.MAX_VALUE;
if (divisor == -1 && dividend == Integer.MIN_VALUE)
return Integer.MAX_VALUE;
//get positive values
long pDividend = Math.abs((long) dividend);
long pDivisor = Math.abs((long) divisor);
int ans = 0;
while (pDividend >= pDivisor) {
//calculate number of left shifts
int numShift = 0;
while (pDividend >= (pDivisor<< numShift)) {
numShift++;
}
//dividend minus the largest shifted divisor
ans += 1<< (numShift - 1);
pDividend -= (pDivisor<< (numShift - 1));
}
if ((dividend > 0 && divisor > 0) || (dividend<0 && divisor<0)) {
return ans;
} else {
return -ans;
}
}
Complexity
- ⏰ Time complexity:
O(log n)
- 🧺 Space complexity:
O(1)