Facebook Pixel

29. Divide Two Integers

MediumBit ManipulationMath
Leetcode Link

Problem Description

This problem asks you to implement integer division between two numbers (dividend and divisor) without using the multiplication (*), division (/), or modulo (%) operators.

The division should follow truncation rules toward zero, meaning:

  • Positive results lose their decimal part (e.g., 8.345 becomes 8)
  • Negative results also truncate toward zero (e.g., -2.7335 becomes -2)

The function should return the quotient (the integer result of the division).

Key Constraints:

  • The environment only supports 32-bit signed integers with range [-2^31, 2^31 - 1]
  • If the actual quotient exceeds 2^31 - 1, return 2^31 - 1 (overflow case)
  • If the actual quotient is less than -2^31, return -2^31 (underflow case)

Solution Strategy: The solution uses repeated subtraction with bit manipulation optimization. Since division is essentially counting how many times the divisor can be subtracted from the dividend, the naive approach would subtract the divisor one at a time. However, this is inefficient for large numbers.

The optimization uses bit shifting (doubling) to speed up the process:

  1. Convert both numbers to negative to avoid overflow issues (since -2^31 cannot be represented as a positive 32-bit integer)
  2. For each iteration, find the largest multiple of the divisor (using left shifts to double it) that can be subtracted from the current dividend
  3. Subtract this multiple and add the corresponding count to the answer
  4. Repeat until the remaining dividend is smaller than the divisor
  5. Apply the correct sign to the final result

The bit shifting approach reduces time complexity from O(dividend/divisor) to O(log(dividend/divisor)).

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

Think about how we learned division in elementary school - it's essentially repeated subtraction. If we want to divide 20 by 3, we keep subtracting 3 from 20 until we can't subtract anymore: 20 - 3 - 3 - 3 - 3 - 3 - 3 = 2. We subtracted 6 times, so 20 ÷ 3 = 6.

The naive approach would be to implement this directly - keep subtracting the divisor from the dividend and count how many times we can do it. But imagine dividing 2^31 - 1 by 1 - we'd need to subtract over 2 billion times! This would definitely timeout.

The key insight is that we can subtract larger chunks at once. Instead of subtracting the divisor one at a time, what if we could subtract divisor * 2, divisor * 4, divisor * 8, and so on? But wait - we can't use multiplication!

This is where bit shifting comes in. Left shifting a number by 1 position (x << 1) doubles it without using multiplication. So we can create multiples of the divisor using shifts: divisor << 1 is 2 * divisor, divisor << 2 is 4 * divisor, etc.

The strategy becomes: find the largest multiple of the divisor (created by shifting) that still fits into the dividend, subtract it, and repeat. It's like taking the biggest possible bite each time instead of nibbling.

For example, dividing 20 by 3:

  • Can we subtract 3 << 2 = 12? Yes! Now we have 20 - 12 = 8, and we've effectively subtracted 4 times
  • Can we subtract 3 << 1 = 6 from 8? Yes! Now we have 8 - 6 = 2, adding 2 more to our count
  • Can we subtract 3 from 2? No, we're done. Total count: 4 + 2 = 6

One tricky detail: why convert everything to negative? In 32-bit signed integers, the range is [-2^31, 2^31 - 1]. Notice that -2^31 has no positive counterpart - converting it to positive would overflow! By working with negatives throughout, we avoid this edge case since all positive numbers can be safely converted to negative.

Learn more about Math patterns.

Solution Approach

Let's walk through the implementation step by step:

1. Handle Special Cases:

if b == 1:
    return a
if a == -(2**31) and b == -1:
    return 2**31 - 1
  • If divisor is 1, the quotient is simply the dividend
  • The overflow case: -2^31 ÷ -1 = 2^31, which exceeds our limit, so we return 2^31 - 1

2. Determine the Sign:

sign = (a > 0 and b > 0) or (a < 0 and b < 0)

The result is positive if both numbers have the same sign, negative otherwise.

3. Convert to Negative Numbers:

a = -a if a > 0 else a
b = -b if b > 0 else b

As discussed, we work with negatives to avoid overflow. Both a (dividend) and b (divisor) are converted to negative values.

4. Main Division Loop:

ans = 0
while a <= b:  # Note: both are negative, so <= means |a| >= |b|

Continue as long as the absolute value of dividend is greater than or equal to the absolute value of divisor.

5. Find Largest Subtractable Multiple:

x = b
cnt = 1
while x >= (-(2**30)) and a <= (x << 1):
    x <<= 1
    cnt <<= 1
  • Start with x = b (the divisor) and cnt = 1 (representing how many divisors this equals)
  • Double x using left shift (x << 1) as long as:
    • x >= -(2^30): Prevents overflow when doubling (since -(2^30) << 1 = -(2^31))
    • a <= (x << 1): The doubled value still fits into the dividend
  • Each time we double x, we also double cnt to track the multiple

6. Subtract and Accumulate:

a -= x
ans += cnt

Subtract the largest multiple found from the dividend and add the corresponding count to our answer.

7. Apply Sign and Return:

return ans if sign else -ans

Apply the sign determined in step 2 to get the final result.

Example Walkthrough: 20 ÷ 3

  • After conversion to negatives: a = -20, b = -3
  • First iteration:
    • Find largest multiple: -3 → -6 → -12 (stop at -12 since -24 would exceed -20)
    • Subtract: -20 - (-12) = -8, add cnt = 4 to answer
  • Second iteration:
    • Find largest multiple: -3 → -6 (stop at -6 since -12 would exceed -8)
    • Subtract: -8 - (-6) = -2, add cnt = 2 to answer
  • -2 > -3, so loop ends
  • Result: 4 + 2 = 6

The time complexity is O(log n) where n is the quotient, since we're essentially doing binary search on the quotient value through bit shifting.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through dividing 15 ÷ 4 using the bit-shifting solution approach:

Initial Setup:

  • Dividend = 15, Divisor = 4
  • Sign will be positive (both numbers are positive)
  • Convert to negatives: a = -15, b = -4
  • Initialize ans = 0

Iteration 1:

  • Start with a = -15, need to find largest multiple of -4 that fits
  • Build multiples by doubling:
    • x = -4, cnt = 1
    • Can we double? Check if -15 <= (-4 << 1) = -8? Yes! So x = -8, cnt = 2
    • Can we double? Check if -15 <= (-8 << 1) = -16? No! Stop here
  • Subtract the largest multiple: a = -15 - (-8) = -7
  • Add to answer: ans = 0 + 2 = 2

Iteration 2:

  • Start with a = -7, find largest multiple of -4 that fits
  • Build multiples:
    • x = -4, cnt = 1
    • Can we double? Check if -7 <= (-4 << 1) = -8? No! Stop here
  • Subtract: a = -7 - (-4) = -3
  • Add to answer: ans = 2 + 1 = 3

Check Loop Condition:

  • Is a = -3 still <= b = -4? No! (Remember, both are negative)
  • Exit loop

Final Result:

  • Apply sign (positive): ans = 3
  • Return 3

Verification: 15 ÷ 4 = 3 with remainder 3, which truncates to 3

The key insight: instead of subtracting 4 three times (naive approach), we subtracted 8 once (which equals subtracting 4 twice) and then 4 once more - reducing our iterations from 3 to 2.

Solution Implementation

1class Solution:
2    def divide(self, dividend: int, divisor: int) -> int:
3        # Handle edge case: dividing by 1 returns the dividend itself
4        if divisor == 1:
5            return dividend
6      
7        # Handle overflow case: INT_MIN / -1 would overflow, return INT_MAX
8        INT_MIN = -(2**31)
9        INT_MAX = 2**31 - 1
10        if dividend == INT_MIN and divisor == -1:
11            return INT_MAX
12      
13        # Determine if result should be positive (same signs) or negative (different signs)
14        is_positive = (dividend > 0 and divisor > 0) or (dividend < 0 and divisor < 0)
15      
16        # Convert both numbers to negative to avoid overflow issues
17        # (negative range is larger than positive range in 32-bit integers)
18        dividend = -dividend if dividend > 0 else dividend
19        divisor = -divisor if divisor > 0 else divisor
20      
21        # Perform division using bit manipulation and subtraction
22        quotient = 0
23        while dividend <= divisor:  # Both are negative, so <= means abs(dividend) >= abs(divisor)
24            # Find the largest multiple of divisor that can be subtracted from dividend
25            current_divisor = divisor
26            current_quotient = 1
27          
28            # Double the divisor using left shift until it exceeds dividend
29            # Check >= -(2^30) to prevent overflow when shifting
30            while current_divisor >= -(2**30) and dividend <= (current_divisor << 1):
31                current_divisor <<= 1  # Multiply by 2
32                current_quotient <<= 1  # Multiply by 2
33          
34            # Subtract the largest found multiple from dividend
35            dividend -= current_divisor
36            quotient += current_quotient
37      
38        # Apply the correct sign to the result
39        return quotient if is_positive else -quotient
40
1class Solution {
2    public int divide(int dividend, int divisor) {
3        // Fast path: dividing by 1 returns the dividend itself
4        if (divisor == 1) {
5            return dividend;
6        }
7      
8        // Handle overflow case: MIN_VALUE / -1 would overflow to a value larger than MAX_VALUE
9        if (dividend == Integer.MIN_VALUE && divisor == -1) {
10            return Integer.MAX_VALUE;
11        }
12      
13        // Determine if the result should be positive (same signs) or negative (different signs)
14        boolean isPositiveResult = (dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0);
15      
16        // Convert both numbers to negative to avoid overflow issues
17        // (negative range is larger than positive range in two's complement)
18        dividend = dividend > 0 ? -dividend : dividend;
19        divisor = divisor > 0 ? -divisor : divisor;
20      
21        int quotient = 0;
22      
23        // Perform division using bit manipulation and subtraction
24        while (dividend <= divisor) {
25            // Start with the divisor and count how many times we can double it
26            int currentDivisor = divisor;
27            int currentQuotient = 1;
28          
29            // Double the divisor using left shift until it exceeds the dividend
30            // Check for overflow before shifting to prevent issues
31            while (currentDivisor >= (Integer.MIN_VALUE >> 1) && dividend <= (currentDivisor << 1)) {
32                currentDivisor <<= 1;  // Double the divisor
33                currentQuotient <<= 1;  // Double the quotient count
34            }
35          
36            // Add the current quotient to the total
37            quotient += currentQuotient;
38          
39            // Subtract the largest found multiple from the dividend
40            dividend -= currentDivisor;
41        }
42      
43        // Apply the correct sign to the result
44        return isPositiveResult ? quotient : -quotient;
45    }
46}
47
1class Solution {
2public:
3    int divide(int dividend, int divisor) {
4        // Handle edge case: divisor is 1, return dividend as is
5        if (divisor == 1) {
6            return dividend;
7        }
8      
9        // Handle overflow case: INT_MIN / -1 would overflow to INT_MAX + 1
10        if (dividend == INT_MIN && divisor == -1) {
11            return INT_MAX;
12        }
13      
14        // Determine if result should be positive (both same sign)
15        bool isPositive = (dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0);
16      
17        // Convert both numbers to negative to avoid overflow issues
18        // (negative range is larger than positive range for int)
19        dividend = dividend > 0 ? -dividend : dividend;
20        divisor = divisor > 0 ? -divisor : divisor;
21      
22        int quotient = 0;
23      
24        // Perform division using bit manipulation and subtraction
25        while (dividend <= divisor) {
26            int currentDivisor = divisor;
27            int currentQuotient = 1;
28          
29            // Double the divisor using left shift until it exceeds dividend
30            // Check for overflow before shifting
31            while (currentDivisor >= (INT_MIN >> 1) && dividend <= (currentDivisor << 1)) {
32                currentDivisor <<= 1;  // Double the divisor
33                currentQuotient <<= 1; // Double the quotient count
34            }
35          
36            // Add current quotient to result
37            quotient += currentQuotient;
38          
39            // Subtract the largest found multiple from dividend
40            dividend -= currentDivisor;
41        }
42      
43        // Apply the correct sign to the result
44        return isPositive ? quotient : -quotient;
45    }
46};
47
1/**
2 * Divides two integers without using multiplication, division, or mod operator
3 * @param dividend - The number to be divided
4 * @param divisor - The number to divide by
5 * @returns The quotient of dividend / divisor, truncated towards zero
6 */
7function divide(dividend: number, divisor: number): number {
8    // Handle edge case: divisor is 1
9    if (divisor === 1) {
10        return dividend;
11    }
12  
13    // Handle edge case: overflow when dividing INT_MIN by -1
14    // Result would be 2^31 which exceeds INT_MAX (2^31 - 1)
15    if (dividend === -(2 ** 31) && divisor === -1) {
16        return 2 ** 31 - 1;
17    }
18
19    // Determine if result should be positive
20    // True if both numbers have the same sign
21    const isPositiveResult: boolean = (dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0);
22  
23    // Convert both numbers to negative to avoid overflow issues
24    // Negative range is larger than positive range in 32-bit integers
25    dividend = dividend > 0 ? -dividend : dividend;
26    divisor = divisor > 0 ? -divisor : divisor;
27  
28    let quotient: number = 0;
29
30    // Repeatedly subtract divisor from dividend
31    while (dividend <= divisor) {
32        // Current subtractor and its corresponding quotient contribution
33        let currentDivisor: number = divisor;
34        let currentQuotient: number = 1;
35
36        // Double the divisor until it exceeds half of dividend
37        // Use bit shifting for efficient doubling
38        // Check >= -(2^30) to prevent overflow when shifting
39        while (currentDivisor >= -(2 ** 30) && dividend <= currentDivisor << 1) {
40            currentDivisor <<= 1;  // Double the divisor
41            currentQuotient <<= 1;  // Double the quotient contribution
42        }
43
44        // Add the current quotient contribution to total
45        quotient += currentQuotient;
46        // Subtract the current divisor from dividend
47        dividend -= currentDivisor;
48    }
49
50    // Apply the correct sign to the result
51    return isPositiveResult ? quotient : -quotient;
52}
53

Time and Space Complexity

The time complexity of this division algorithm is O(log a × log b), where a is the dividend and b is the divisor.

The algorithm works by repeatedly subtracting multiples of the divisor from the dividend. The outer while loop runs at most O(log a) times because in each iteration, we subtract at least the divisor b from a, and in the worst case, we need a/b iterations which is bounded by O(log a) when we consider the doubling optimization.

The inner while loop performs bit shifting operations to find the largest multiple of b (in the form of b × 2^k) that can be subtracted from the current value of a. This loop runs at most O(log b) times in each iteration of the outer loop, as we double x each time until it exceeds a or reaches the boundary condition.

Since the inner loop runs O(log b) times for each of the O(log a) iterations of the outer loop, the total time complexity is O(log a × log b).

The space complexity is O(1) as the algorithm only uses a constant amount of extra space for variables like sign, ans, x, and cnt, regardless of the input size.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Integer Overflow When Working with Positive Numbers

The Pitfall: Many developers initially try to work with positive numbers by converting negative inputs to positive. This fails for the edge case where dividend = -2^31 because 2^31 cannot be represented in a 32-bit signed integer (maximum is 2^31 - 1).

# WRONG approach - causes overflow
dividend = abs(dividend)  # This fails when dividend = -2^31
divisor = abs(divisor)

The Solution: Always convert to negative numbers instead, since the negative range [-2^31, -1] is larger than the positive range [1, 2^31-1]:

# CORRECT approach
dividend = -dividend if dividend > 0 else dividend
divisor = -divisor if divisor > 0 else divisor

2. Overflow During Bit Shifting

The Pitfall: When doubling the divisor using left shift, forgetting to check for potential overflow can cause incorrect results or runtime errors:

# WRONG - no overflow check
while dividend <= (current_divisor << 1):
    current_divisor <<= 1
    current_quotient <<= 1

The Solution: Add a boundary check before shifting. Since we're working with negative numbers, check that the current value is >= -2^30 before doubling (because -2^30 << 1 = -2^31, which is the limit):

# CORRECT - includes overflow prevention
while current_divisor >= -(2**30) and dividend <= (current_divisor << 1):
    current_divisor <<= 1
    current_quotient <<= 1

3. Incorrect Sign Determination Logic

The Pitfall: Using XOR or other complex logic for sign determination can be error-prone:

# Confusing and error-prone
is_positive = (dividend < 0) ^ (divisor < 0) == 0

The Solution: Use clear, explicit logic that's easy to understand and verify:

# CORRECT and clear
is_positive = (dividend > 0 and divisor > 0) or (dividend < 0 and divisor < 0)

4. Forgetting the Special Overflow Case

The Pitfall: Not handling the specific case of -2^31 ÷ -1, which mathematically equals 2^31 but exceeds the 32-bit signed integer range:

# WRONG - missing overflow handling
def divide(dividend, divisor):
    # ... rest of the code without checking for INT_MIN / -1

The Solution: Always check for this case explicitly at the beginning:

# CORRECT
if dividend == -(2**31) and divisor == -1:
    return 2**31 - 1

5. Incorrect Comparison Direction with Negative Numbers

The Pitfall: When working with negative numbers, the comparison operators can be counterintuitive:

# WRONG - using > instead of <= for negative numbers
while dividend > divisor:  # This is wrong when both are negative

The Solution: Remember that for negative numbers, a "smaller" value actually has a larger absolute value:

# CORRECT
while dividend <= divisor:  # -20 <= -3 means |20| >= |3|
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

What are the most two important steps in writing a depth first search function? (Select 2)


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More