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: [−231, 231 − 1]
. For this problem, if the quotient is strictly greater than 231 - 1
, then return 231 - 1
, and if the quotient is strictly less than -231
, then return -231
.
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.
Constraints:
-231 <= dividend, divisor <= 231 - 1
divisor != 0
This problem challenges you to implement integer division without using the multiplication, division, or modulo operators. The solution leverages bit manipulation and a clever approach to simulate division through repeated subtraction. However, naive repeated subtraction is inefficient. The optimal solution uses a technique similar to binary exponentiation to speed up the process significantly.
Core Idea:
The core idea is to repeatedly subtract the divisor from the dividend, but not just one divisor at a time. Instead, we try to subtract multiples of the divisor (powers of 2) to accelerate the process.
Algorithm:
Handle Special Cases:
divisor == 0
(throws exception or returns error code).dividend == INT_MIN
and divisor == -1
(handles potential overflow).Determine Sign:
Convert to Negative:
dividend
and divisor
to their negative counterparts. This is crucial to avoid overflow when handling INT_MIN
.Iterative Subtraction with Bit Shifting:
quotient = 0
.dividend <= divisor
:
temp_divisor = divisor
and multiplier = 1
.temp_divisor
and multiplier
(temp_divisor <<= 1
; multiplier <<= 1
) until doubling temp_divisor
would make it greater than the dividend.temp_divisor
from dividend
(dividend -= temp_divisor
).multiplier
to the quotient
(quotient += multiplier
).Adjust Sign:
quotient
.Handle Overflow:
quotient
after ensuring it's within the 32-bit signed integer range (INT_MIN
to INT_MAX
).Time Complexity Analysis:
The time complexity is O(log n), where n is the absolute value of the dividend. This is because each iteration of the while
loop effectively halves the remaining dividend (in the best case) due to the doubling of temp_divisor
. The number of times you can halve a number before reaching 1 is approximately log₂(n).
Space Complexity Analysis:
The space complexity is O(1) because we only use a constant number of variables regardless of the input size.
Code Examples (Python):
def divide(dividend: int, divisor: int) -> int:
if divisor == 0:
raise ZeroDivisionError("Cannot divide by zero")
if dividend == -2**31 and divisor == -1:
return 2**31 - 1 # Handle potential overflow
sign = (dividend < 0) ^ (divisor < 0) # XOR for sign determination
dividend = abs(dividend)
divisor = abs(divisor)
quotient = 0
while dividend >= divisor:
temp_divisor = divisor
multiplier = 1
while dividend >= temp_divisor << 1: # Efficient doubling with bit shift
temp_divisor <<= 1
multiplier <<= 1
dividend -= temp_divisor
quotient += multiplier
return quotient if not sign else -quotient
The other languages (Java, C++, Go, TypeScript, C#, PHP) would implement the same logic using their respective syntax and data types. The core bit-shifting optimization and iterative subtraction strategy remain the same across all languages.