0029. Divide Two Integers¶
Table of Contents¶
- Problem
- Problem Breakdown
- Approach 1: Repeated Subtraction
- Approach 2: Exponential Search (Bit Shifting)
- Complexity Comparison
- Edge Cases
- Common Mistakes
- Related Problems
- Visual Animation
Problem¶
| Leetcode | 29. Divide Two Integers |
| Difficulty | |
| Tags | Math, Bit Manipulation |
Description¶
Given two integers
dividendanddivisor, 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.345would be truncated to8, and-2.7335would be truncated to-2.Return the quotient after dividing
dividendbydivisor.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 than2^31 - 1, then return2^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 = -2
Output: -3
Explanation: 7 / -2 = -3.5, which is truncated to -3.
Example 3:
Input: dividend = -2147483648, divisor = -1
Output: 2147483647
Explanation: -2147483648 / -1 = 2147483648, which overflows 32-bit int.
Return 2^31 - 1 = 2147483647.
Constraints¶
-2^31 <= dividend, divisor <= 2^31 - 1divisor != 0
Problem Breakdown¶
1. What is being asked?¶
Implement integer division without using *, /, or % operators. The result must truncate toward zero and handle 32-bit signed integer overflow.
2. What is the input?¶
| Parameter | Type | Description |
|---|---|---|
dividend | int | The number being divided |
divisor | int | The number to divide by |
Important observations about the input: - Both values can be negative - divisor is never zero - The range is [-2^31, 2^31 - 1] (asymmetric!) - dividend = -2^31 and divisor = -1 causes overflow
3. What is the output?¶
- A single integer -- the truncated quotient of
dividend / divisor - Must be clamped to
[-2^31, 2^31 - 1]
4. Constraints analysis¶
| Constraint | Significance |
|---|---|
No *, /, % | Must use addition, subtraction, and bit shifts |
| 32-bit signed range | Only one overflow case: -2^31 / -1 |
| Truncate toward zero | 7 / -2 = -3 (not -4). Negative results round toward zero |
divisor != 0 | No need to handle division by zero |
5. Step-by-step example analysis¶
Example 1: dividend = 10, divisor = 3¶
10 / 3 = ?
How many times does 3 fit into 10?
3 * 1 = 3 (10 - 3 = 7, still >= 3)
3 * 2 = 6 (10 - 6 = 4, still >= 3)
3 * 3 = 9 (10 - 9 = 1, now < 3)
Answer: 3 (remainder 1)
Example 2: dividend = 7, divisor = -2¶
7 / -2 = ?
Different signs -> result is negative
Work with absolute values: 7 / 2
2 * 1 = 2 (7 - 2 = 5)
2 * 2 = 4 (7 - 4 = 3)
2 * 3 = 6 (7 - 6 = 1, now < 2)
|quotient| = 3, apply negative sign -> -3
Example 3: dividend = -2147483648, divisor = -1¶
-2147483648 / -1 = 2147483648
But 2147483648 > 2^31 - 1 = 2147483647 (overflow!)
Clamp to 2147483647
6. Key Observations¶
- Sign handling -- Determine the sign from the inputs, then work with absolute values.
- Only one overflow case --
-2^31 / -1 = 2^31which exceedsINT_MAX. All other divisions produce results within range. - Subtraction is slow -- Subtracting divisor one at a time is O(dividend/divisor), which can be 2^31 for
dividend = 2^31, divisor = 1. - Doubling trick -- Instead of subtracting divisor once, double it repeatedly (using bit shifts) to subtract large chunks at once.
7. Pattern identification¶
| Pattern | Why it fits | Example |
|---|---|---|
| Repeated Subtraction | Conceptually simple, subtract divisor until remainder < divisor | Educational but TLE |
| Exponential Search | Double the divisor via left shift, subtract largest power-of-2 multiples first | Optimal: O(log^2 n) |
Chosen pattern: Exponential Search (Bit Shifting) Reason: By doubling the divisor, we reduce the dividend exponentially fast, achieving O(log^2 n) time.
Approach 1: Repeated Subtraction¶
Thought process¶
The most intuitive approach: "How many times can I subtract divisor from dividend?" Keep subtracting and counting until the remainder is less than the divisor. This works but is extremely slow for large dividends with small divisors.
Algorithm (step-by-step)¶
- Handle the overflow edge case:
dividend = -2^31anddivisor = -1-> return2^31 - 1 - Determine the sign of the result (negative if signs differ)
- Work with absolute values of dividend and divisor
- Repeatedly subtract divisor from dividend, incrementing quotient each time
- Stop when remainder < divisor
- Apply sign and return
Pseudocode¶
function divide(dividend, divisor):
if dividend == -2^31 and divisor == -1:
return 2^31 - 1
negative = (dividend < 0) XOR (divisor < 0)
a = abs(dividend)
b = abs(divisor)
quotient = 0
while a >= b:
a -= b
quotient += 1
return -quotient if negative else quotient
Complexity¶
| Complexity | Explanation | |
|---|---|---|
| Time | O(dividend / divisor) | Worst case: 2^31 / 1 = 2 billion subtractions. TLE! |
| Space | O(1) | Only a few variables. |
Implementation¶
Go¶
func divide(dividend int, divisor int) int {
// Overflow edge case
if dividend == math.MinInt32 && divisor == -1 {
return math.MaxInt32
}
negative := (dividend < 0) != (divisor < 0)
a, b := abs(dividend), abs(divisor)
quotient := 0
for a >= b {
a -= b
quotient++
}
if negative {
return -quotient
}
return quotient
}
Java¶
class Solution {
public 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);
int quotient = 0;
while (a >= b) {
a -= b;
quotient++;
}
return negative ? -quotient : quotient;
}
}
Python¶
class Solution:
def divide(self, dividend: int, divisor: int) -> int:
INT_MAX = 2**31 - 1
INT_MIN = -(2**31)
if dividend == INT_MIN and divisor == -1:
return INT_MAX
negative = (dividend < 0) != (divisor < 0)
a, b = abs(dividend), abs(divisor)
quotient = 0
while a >= b:
a -= b
quotient += 1
return -quotient if negative else quotient
Dry Run¶
Input: dividend = 10, divisor = 3
negative = False (both positive)
a = 10, b = 3
Step 1: a = 10 >= 3 -> a = 10 - 3 = 7, quotient = 1
Step 2: a = 7 >= 3 -> a = 7 - 3 = 4, quotient = 2
Step 3: a = 4 >= 3 -> a = 4 - 3 = 1, quotient = 3
Step 4: a = 1 < 3 -> STOP
Result: 3
Total subtractions: 3
Approach 2: Exponential Search (Bit Shifting)¶
The problem with Repeated Subtraction¶
Subtracting one divisor at a time is O(dividend/divisor). For
dividend = 2^31, divisor = 1, that is ~2 billion operations -- TLE. Question: "Can we subtract larger chunks to speed this up?"
Optimization idea¶
Double the divisor using left shifts (
<< 1) until it would exceed the remaining dividend. Then subtract that largest doubled value and add the corresponding power of 2 to the quotient. Repeat with the remaining dividend.Example:
43 / 3-3 << 0 = 3,3 << 1 = 6,3 << 2 = 12,3 << 3 = 24,3 << 4 = 48 > 43-> stop - Subtract24(=3 * 8), quotient +=8, remainder =43 - 24 = 19-3 << 0 = 3,3 << 1 = 6,3 << 2 = 12,3 << 3 = 24 > 19-> stop - Subtract12(=3 * 4), quotient +=4, remainder =19 - 12 = 7-3 << 0 = 3,3 << 1 = 6,3 << 2 = 12 > 7-> stop - Subtract6(=3 * 2), quotient +=2, remainder =7 - 6 = 1-1 < 3-> STOP - Total quotient =8 + 4 + 2 = 14
Algorithm (step-by-step)¶
- Handle the overflow edge case:
dividend = -2^31anddivisor = -1-> return2^31 - 1 - Determine the sign of the result
- Work with absolute values (using
long/ 64-bit to avoid overflow with-2^31) - While
remainder >= divisor: a. Start withtemp = divisor,multiple = 1b. Whileremainder >= temp << 1(and no overflow): doubletempandmultiplec. Subtracttempfrom remainder, addmultipleto quotient - Apply sign, clamp to 32-bit range, and return
Pseudocode¶
function divide(dividend, divisor):
if dividend == -2^31 and divisor == -1:
return 2^31 - 1
negative = (dividend < 0) XOR (divisor < 0)
a = abs(dividend) // use 64-bit
b = abs(divisor) // use 64-bit
quotient = 0
while a >= b:
temp = b
multiple = 1
while a >= temp << 1:
temp <<= 1
multiple <<= 1
a -= temp
quotient += multiple
return -quotient if negative else quotient
Complexity¶
| Complexity | Explanation | |
|---|---|---|
| Time | O(log^2 n) | Outer loop runs O(log n) times (quotient halves each iteration). Inner loop runs O(log n) to find the largest power. |
| Space | O(1) | Only a few variables. |
Implementation¶
Go¶
func divide(dividend int, divisor int) int {
// Overflow edge case
if dividend == math.MinInt32 && divisor == -1 {
return math.MaxInt32
}
// Determine sign
negative := (dividend < 0) != (divisor < 0)
// Work with absolute values (use int64 to handle -2^31)
a := int64(dividend)
if a < 0 {
a = -a
}
b := int64(divisor)
if b < 0 {
b = -b
}
quotient := int64(0)
for a >= b {
temp := b
multiple := int64(1)
// Double temp until it would exceed a
for a >= temp<<1 {
temp <<= 1
multiple <<= 1
}
a -= temp
quotient += multiple
}
if negative {
quotient = -quotient
}
// Clamp to 32-bit range
if quotient > math.MaxInt32 {
return math.MaxInt32
}
if quotient < math.MinInt32 {
return math.MinInt32
}
return int(quotient)
}
Java¶
class Solution {
public int divide(int dividend, int divisor) {
// Overflow edge case
if (dividend == Integer.MIN_VALUE && divisor == -1) {
return Integer.MAX_VALUE;
}
// Determine sign
boolean negative = (dividend < 0) != (divisor < 0);
// Work with absolute values (use long to handle -2^31)
long a = Math.abs((long) dividend);
long b = Math.abs((long) divisor);
long quotient = 0;
while (a >= b) {
long temp = b;
long multiple = 1;
// Double temp until it would exceed a
while (a >= temp << 1) {
temp <<= 1;
multiple <<= 1;
}
a -= temp;
quotient += multiple;
}
return negative ? (int) -quotient : (int) quotient;
}
}
Python¶
class Solution:
def divide(self, dividend: int, divisor: int) -> int:
INT_MAX = 2**31 - 1
INT_MIN = -(2**31)
# Overflow edge case
if dividend == INT_MIN and divisor == -1:
return INT_MAX
# Determine sign
negative = (dividend < 0) != (divisor < 0)
# Work with absolute values
a, b = abs(dividend), abs(divisor)
quotient = 0
while a >= b:
temp, multiple = b, 1
# Double temp until it would exceed a
while a >= temp << 1:
temp <<= 1
multiple <<= 1
a -= temp
quotient += multiple
return -quotient if negative else quotient
Dry Run¶
Input: dividend = 43, divisor = 3
negative = False
a = 43, b = 3, quotient = 0
--- Outer iteration 1 ---
temp = 3, multiple = 1
43 >= 3<<1 = 6? Yes -> temp=6, multiple=2
43 >= 6<<1 = 12? Yes -> temp=12, multiple=4
43 >= 12<<1 = 24? Yes -> temp=24, multiple=8
43 >= 24<<1 = 48? No -> STOP
a = 43 - 24 = 19, quotient = 0 + 8 = 8
--- Outer iteration 2 ---
temp = 3, multiple = 1
19 >= 6? Yes -> temp=6, multiple=2
19 >= 12? Yes -> temp=12, multiple=4
19 >= 24? No -> STOP
a = 19 - 12 = 7, quotient = 8 + 4 = 12
--- Outer iteration 3 ---
temp = 3, multiple = 1
7 >= 6? Yes -> temp=6, multiple=2
7 >= 12? No -> STOP
a = 7 - 6 = 1, quotient = 12 + 2 = 14
--- Outer iteration 4 ---
a = 1 < b = 3 -> STOP
Result: 14
Verification: 43 / 3 = 14.333... -> truncated to 14 โ
Complexity Comparison¶
| # | Approach | Time | Space | Pros | Cons |
|---|---|---|---|---|---|
| 1 | Repeated Subtraction | O(n) | O(1) | Simple, easy to understand | TLE for large inputs |
| 2 | Exponential Search | O(log^2 n) | O(1) | Fast, passes all test cases | Slightly more complex logic |
Where n = |dividend / divisor|.
Which solution to choose?¶
- In an interview: Approach 2 (Exponential Search) -- demonstrates understanding of bit manipulation and optimization
- In production: Use the language's built-in
/operator (this is a puzzle problem) - On Leetcode: Approach 2 -- only O(log^2 n) passes within the time limit
- For learning: Both -- Repeated Subtraction to understand the concept, Exponential Search to learn bit shifting patterns
Edge Cases¶
| # | Case | Input | Expected Output | Reason |
|---|---|---|---|---|
| 1 | Overflow case | dividend=-2147483648, divisor=-1 | 2147483647 | Result exceeds INT_MAX, clamp |
| 2 | Negative dividend | dividend=7, divisor=-2 | -3 | Truncate toward zero |
| 3 | Negative divisor | dividend=-7, divisor=2 | -3 | Truncate toward zero |
| 4 | Both negative | dividend=-7, divisor=-2 | 3 | Negatives cancel out |
| 5 | Divisor = 1 | dividend=100, divisor=1 | 100 | Identity division |
| 6 | Divisor = -1 | dividend=100, divisor=-1 | -100 | Negate the result |
| 7 | Dividend = 0 | dividend=0, divisor=5 | 0 | Zero divided by anything is 0 |
| 8 | Dividend < divisor | dividend=1, divisor=3 | 0 | Truncated to 0 |
| 9 | Dividend = MIN_INT | dividend=-2147483648, divisor=1 | -2147483648 | Large negative, divisor=1 |
| 10 | Equal values | dividend=7, divisor=7 | 1 | Any number / itself = 1 |
Common Mistakes¶
Mistake 1: Not handling the -2^31 absolute value overflow¶
# WRONG -- abs(-2147483648) overflows in 32-bit int!
a = abs(dividend) # In Java/Go, abs(Integer.MIN_VALUE) = Integer.MIN_VALUE
# CORRECT -- cast to long/int64 first
a = abs((long) dividend) // Java
a = int64(dividend); if a < 0 { a = -a } // Go
Reason: -2^31 has no positive counterpart in 32-bit signed integers since 2^31 > INT_MAX.
Mistake 2: Infinite loop when doubling temp¶
# WRONG -- temp<<1 can overflow, causing infinite loop
while a >= temp << 1:
temp <<= 1
multiple <<= 1
# SAFER -- add overflow guard
while a >= temp << 1 and temp << 1 > 0:
temp <<= 1
multiple <<= 1
Reason: In languages with fixed-width integers, shifting left can cause overflow to negative, breaking the comparison.
Mistake 3: Wrong sign handling¶
# WRONG -- using multiplication to determine sign
negative = dividend * divisor < 0 # Can overflow!
# CORRECT -- use XOR of sign bits
negative = (dividend < 0) != (divisor < 0)
Reason: Multiplying two large negative numbers can overflow.
Mistake 4: Not truncating toward zero¶
# WRONG -- Python's // truncates toward negative infinity
result = abs(dividend) // abs(divisor) # For 7 // -2, Python gives -4
# CORRECT -- work with absolute values, apply sign manually
quotient = abs(dividend) // abs(divisor)
result = -quotient if negative else quotient # -3, correct
Related Problems¶
| # | Problem | Difficulty | Similarity |
|---|---|---|---|
| 1 | 50. Pow(x, n) | Exponential search / binary exponentiation | |
| 2 | 69. Sqrt(x) | Binary search on answer | |
| 3 | 166. Fraction to Recurring Decimal | Division with edge cases | |
| 4 | 371. Sum of Two Integers | Bit manipulation arithmetic | |
| 5 | 67. Add Binary | Arithmetic without built-in operators |
Visual Animation¶
Interactive animation: animation.html
In the animation: - Visual representation of dividend being reduced by doubling divisor - Bit shifting visualization showing
divisor << 0,divisor << 1,divisor << 2, ... - Step-by-step decomposition of quotient into powers of 2 - Preset examples including the overflow edge case