Bit Manipulation · 8 of 10
Divide two integers without using multiplication, division and mod operator
Share stickers into packs without a divide button, by taking away the biggest boxes of packs first.
- Simple way
- time O(dividend / divisor)
room O(1) - Clever way
- time O(log n)
room O(1)
The problem, simply
You get two whole numbers, dividend and divisor. Give back dividend / divisor, rounded toward zero, so 3.7 becomes 3 and -3.5 becomes -3.
You may not use *, / or %. You may add, subtract and shift bits. If the true answer is too big for an int, give back Integer.MAX_VALUE.
A story to remember it
Picture it
100 divided by 7. The answer 14 is 1110 in bits: one box of 8 packs (56), one of 4 packs (28) and one of 2 packs (14). 56 + 28 + 14 = 98, and 2 stickers are left over.
- answer
Examples
A normal case
- In
dividend = 100, divisor = 7- Out
14
14 packs of 7 is 98. The 2 left over stickers are dropped.
A negative answer
- In
dividend = -7, divisor = 2- Out
-3
The true answer is -3.5. Rounding toward zero gives -3, not -4.
Both negative
- In
dividend = -10, divisor = -3- Out
3
Two minus signs make a plus. Divide 10 by 3 and keep the answer positive.
The one overflow
- In
dividend = -2147483648, divisor = -1- Out
2147483647
The true answer is 2147483648, one more than the biggest int. The rule says to give back Integer.MAX_VALUE.
Small dividend
- In
dividend = 3, divisor = 5- Out
0
Not even one pack fits.
Way 1: the simple way
Division is taking away the same amount again and again.
- Handle the overflow case first.
- Remember whether the answer is negative: it is when exactly one of the two numbers is negative.
- Make both numbers positive, inside a
longso-2147483648fits. - Subtract the divisor until what is left is smaller than it, counting each time.
class Solution {
public static int divide(int dividend, int divisor) {
if (dividend == Integer.MIN_VALUE && divisor == -1) return Integer.MAX_VALUE;
boolean negative = (dividend < 0) ^ (divisor < 0);
long a = Math.abs((long) dividend);
long b = Math.abs((long) divisor);
long packs = 0;
while (a >= b) {
a -= b; // fill one pack
packs++;
}
return (int) (negative ? -packs : packs);
}
}How long it takes: one round per pack, O(dividend / divisor). Dividing 2 billion by 1 takes 2 billion rounds. Extra room: O(1).
Way 2: the clever way
b << i is b doubled i times, a box of 2^i packs. Try the boxes from the biggest down. Each box is used at most once, because if two boxes of size 2^i fit, one box of size 2^(i+1) would have fit first.
- Handle overflow, the sign, and make both numbers positive
longs. - For
ifrom 31 down to 0: ifb << ifits in what is left, take it away and switch on bitiof the answer. - Put the sign back.
Take away the biggest box that fits
01 / 07
Share 100 stickers into packs of 7. Shifting 7 left by i places makes a box of 2^i packs. The code tries i from 31 down to 0, but for i of 5 and more the box is far bigger than 100, so we start the picture at i = 4.
- dividend
- 100
- divisor
- 7
- done
- answer
- rejected
- just added
- ignored
class Solution {
public static int divide(int dividend, int divisor) {
if (dividend == Integer.MIN_VALUE && divisor == -1) return Integer.MAX_VALUE;
boolean negative = (dividend < 0) ^ (divisor < 0);
long a = Math.abs((long) dividend);
long b = Math.abs((long) divisor);
long packs = 0;
for (int i = 31; i >= 0; i--) {
if ((b << i) <= a) { // a box of 2^i packs fits
a -= b << i; // take it away
packs += 1L << i; // switch on bit i of the answer
}
}
return (int) (negative ? -packs : packs);
}
}How long it takes: exactly 32 tries, one per bit of the answer, O(log n). Extra room: O(1).
Watch out for
- Rounding the wrong way. Java's
/rounds toward zero, and so does dividing the positive values and putting the sign back. Do not round down for negatives. - Shifting in
int.7 << 30overflows anint. Do the shifts inlong, where even2^31 << 31fits. - Dividing by zero. The problem usually promises the divisor is not 0. If not, throw an
ArithmeticException.
What interviewers ask next
- Another fast way? Double the divisor until it is too big, take away the biggest double that fits, and repeat. That is
O(log^2 n), since each round rebuilds the doubles. - What if you may only use 32 bit
ints, nolong? Turn both numbers negative instead, since anintholds one more negative value than positive ones, and flip every comparison. - How would you get the remainder too? It is whatever is left in
aat the end, with the sign of the dividend. - Multiply without
*? The mirror trick: adda << ifor every bitithat is on inb.
Remember this
Grown-up words: the boxes of packs are shifted divisors, filling the biggest box first is binary long division, the leftover is the remainder, and the special case is integer overflow.