The problem
You get a signed 32-bit integer x. Return it with its digits reversed, keeping the sign. If the reversed value falls outside the signed 32-bit range [−2³¹, 2³¹ − 1], return 0.
Input: x = -123
Output: -321The digits 1, 2, 3 reverse to 3, 2, 1, and the minus sign stays. By contrast, 1534236469 reversed is 9646324351, which exceeds 2³¹ − 1, so the answer is 0.
How to think about it
Start with brute force. Turn the number into a string, reverse it, put the sign back, and convert to an integer. In Python this works, but it sidesteps the two things the question is about: handling digits arithmetically and noticing overflow. Interviewers usually ask for the maths version.
The key insight: % 10 pops the last digit and // 10 removes it. Pop digits off x one at a time and push each onto the end of rev with rev = rev * 10 + digit. The last digit of x is pushed first, so it ends up as the most significant digit of rev. That is the reversal, in O(number of digits) steps.
Handle the sign separately. Python’s % and // round towards negative infinity, so -123 % 10 is 7, not 3. The clean fix is to remember the sign, work on abs(x), and reapply the sign at the end.
Overflow is the real question. In Python, integers never overflow, so you can build the full reversed number and check the range once at the end. In Java or C++ that would already have overflowed. There you check before each push: if rev > (2³¹ − 1) / 10 (or equals it and the next digit is above 7), the push would overflow, so return 0. The tell for this pattern is “digits of an integer, 32-bit range”: pop with mod and divide, and guard the bound.
Approach
- Save
signas −1 ifxis negative, else 1. Setx = abs(x). - Start
rev = 0. Whilexis not 0:rev = rev * 10 + x % 10, thenx //= 10. - Multiply
revbysign. - Return
revif it lies in [−2³¹, 2³¹ − 1], otherwise 0.
Solution
def reverse_integer(x):
sign = -1 if x < 0 else 1
x = abs(x) # Python's % on negatives is not what we want
rev = 0
while x:
rev = rev * 10 + x % 10 # push the popped digit
x //= 10 # drop it from x
rev *= sign
return rev if -2**31 <= rev <= 2**31 - 1 else 0 # 32-bit overflow -> 0
# reverse_integer(-123) -> -321 ; reverse_integer(1534236469) -> 0 (overflow)Dry run
On x = -123: sign = -1, so the loop works on x = 123.
| Step | Digit popped (x % 10) |
rev after |
x after |
|---|---|---|---|
| 1 | 3 | 3 | 12 |
| 2 | 2 | 32 | 1 |
| 3 | 1 | 321 | 0 |
The loop stops when x is 0. Reapplying the sign gives −321, which is in range, so the answer is −321.
Complexity
- Time: O(log x). The loop runs once per decimal digit, and a number
xhas about log₁₀ x digits (at most 10 for a 32-bit value). - Space: O(1). A few integers.
Edge cases and pitfalls
- Trailing zeros disappear:
120reverses to21, which is correct. - Zero returns 0: the loop never runs.
- Overflow returns 0, as in
1534236469. In a fixed-width language the check must come before the multiply, not after. - Negative numbers with
%in Python. Usingx % 10directly on a negativexgives wrong digits; strip the sign first. -2³¹is a valid input; its absolute value does not fit in a 32-bit int in Java/C++, so take care there.
Related problems
- Plus One (LeetCode 66): another digit-handling problem, here with carries.
- Reverse Bits (LeetCode 190): the same pop-and-push reversal, in base 2 instead of base 10.
- Roman to Integer (LeetCode 13): builds an integer one symbol at a time.