MediumLeetCode 7Math — digit pop and overflow check

Reverse Integer (LeetCode 7)

Problem 10 of 10 in Math & Geometry — Practice Problems

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: -321

The 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

  1. Save sign as −1 if x is negative, else 1. Set x = abs(x).
  2. Start rev = 0. While x is not 0: rev = rev * 10 + x % 10, then x //= 10.
  3. Multiply rev by sign.
  4. Return rev if 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 x has 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: 120 reverses to 21, 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. Using x % 10 directly on a negative x gives 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.