LeetCode #7 — Medium

Reverse Integer

A complete visual walkthrough of digit-by-digit reversal with overflow detection — from brute force to optimal.

Solve on LeetCode
The Problem

Problem Statement

Given a signed 32-bit integer x, return x with its digits reversed. If reversing x causes the value to go outside the signed 32-bit integer range [-231, 231 - 1], then return 0.

Assume the environment does not allow you to store 64-bit integers (signed or unsigned).

Example 1:

Input: x = 123
Output: 321

Example 2:

Input: x = -123
Output: -321

Example 3:

Input: x = 120
Output: 21

Constraints:

  • -231 <= x <= 231 - 1

Roadmap

  1. Brute Force — String Reversal
  2. The Core Insight — Modulo & Division
  3. Algorithm Walkthrough
  4. The Overflow Problem
  5. Edge Cases
  6. Full Annotated Code
  7. Interactive Demo
  8. Complexity Analysis
Step 01

Brute Force — String Reversal

The first instinct: convert the integer to a string, reverse the characters, then parse it back. Let's trace it with x = -123:

String Approach

input
-
1
2
3
strip sign, reverse chars
reversed
3
2
1
restore sign, parse to int
output
-
3
2
1

This works, but it's clunky. You need to handle the sign separately, strip leading zeros, and you still need to check for overflow before parsing back. The string conversion also uses extra memory for the character array.

// Brute force (still needs overflow check!)
String s = String.valueOf(Math.abs((long)x));
String rev = new StringBuilder(s).reverse().toString();
long val = Long.parseLong(rev) * (x < 0 ? -1 : 1);
return (val > Integer.MAX_VALUE || val < Integer.MIN_VALUE) ? 0 : (int)val;
💡

The real problem isn't reversing digits — it's detecting overflow without using a larger data type. Can we do this with pure math, no strings, no long?

Step 02

The Core Insight — Modulo & Division

We can reverse an integer purely with arithmetic. Two operations are all we need:

Pop & Push

POP (extract last digit)
digit = x % 10
x = x / 10
Peel off the last digit and shrink x by a factor of 10.
PUSH (append to result)
result = result * 10
result = result + digit
Shift result left by one decimal place, then add the new digit.

The beauty: popping digits from x gives them in reverse order. The last digit comes out first, which is exactly where it needs to go in the result. No string manipulation needed.

Quick Example: x = 123

123 % 10
3
pop 3, x becomes 12
12 % 10
2
pop 2, x becomes 1
1 % 10
1
pop 1, x becomes 0 (done!)

Digits came out as 3, 2, 1 — the reverse of 1, 2, 3!

Negative numbers work automatically! In Java, -123 % 10 = -3 and -123 / 10 = -12. The sign is preserved through modulo and division, so no special sign handling is needed.

Step 03

Algorithm Walkthrough

Let's trace the full algorithm with x = 1534, watching digits move from the input to the result one by one.

Iteration 1 — Pop 4, Push 4

x
1
5
3
4
1534 % 10 = 4
pop digit 4
result
4
0 * 10 + 4 = 4

x = 1534 / 10 = 153, result = 4

Iteration 2 — Pop 3, Push 3

x
1
5
3
153 % 10 = 3
pop digit 3
result
4
3
4 * 10 + 3 = 43

x = 153 / 10 = 15, result = 43

Iteration 3 — Pop 5, Push 5

x
1
5
15 % 10 = 5
pop digit 5
result
4
3
5
43 * 10 + 5 = 435

x = 15 / 10 = 1, result = 435

Iteration 4 — Pop 1, Push 1

x
1
1 % 10 = 1
pop digit 1
result
4
3
5
1
435 * 10 + 1 = 4351

x = 1 / 10 = 0 (done!), result = 4351

Step 04

The Overflow Problem

The operation result * 10 + digit can overflow a 32-bit integer. The trick is to check BEFORE the multiplication happens, not after. Once overflow occurs, the value is already corrupted.

Overflow Detection Strategy

The 32-bit signed integer range is [-2,147,483,648 to 2,147,483,647]. We need to check if result * 10 + digit would exceed these bounds.

Positive overflow check
If result > MAX_VALUE / 10 (i.e., result > 214748364), then result * 10 alone would overflow.
If result == MAX_VALUE / 10 and digit > 7, then result * 10 + digit > 2147483647.
Negative overflow check
If result < MIN_VALUE / 10 (i.e., result < -214748364), then result * 10 alone would underflow.
If result == MIN_VALUE / 10 and digit < -8, then result * 10 + digit < -2147483648.
🎯

Why 7 and -8? Because MAX_VALUE = 2,147,483,647 and MIN_VALUE = -2,147,483,648. When result == 214748364, we can only safely add a digit up to 7 (positive) or down to -8 (negative).

Overflow Example: x = 1534236469

Reversed this would be 9646324351, which exceeds 2,147,483,647. The algorithm catches it:

After popping digits: result = 964632435
Next digit to push: 1
Check: 964632435 > 214748364 (MAX/10)
Overflow detected! Return 0.
Step 05

Edge Cases

32-Bit Integer Overflow

The most important edge case. If reversing the digits would produce a number outside [-2,147,483,648, 2,147,483,647], return 0. For example, x = 1534236469 reverses to 9646324351, which exceeds INT_MAX, so the answer is 0. The algorithm detects this before the multiplication corrupts the value.

Negative Numbers

The sign is preserved automatically by the modulo and division operations. In Java (and most languages with C-style truncation), -123 % 10 = -3 and -123 / 10 = -12, so the pop-and-push loop produces -321 without any special sign handling. The overflow check for negatives uses MIN_VALUE: if result < MIN_VALUE / 10 or (result == MIN_VALUE / 10 and digit < -8), return 0.

Numbers Ending in Zeros

Trailing zeros on the input become leading zeros on the reversed number, which are dropped naturally. x = 1200 reverses to 0021, but leading zeros are not stored — the result is simply 21. The algorithm handles this correctly because pushing a 0 digit just multiplies result by 10 and adds 0, and the initial zeros land at the front of the reversed number where they have no effect.

Single-Digit Numbers

Any single-digit integer (-9 through 9) is already its own reverse. The loop runs exactly once: it pops the only digit, the overflow check trivially passes (since |digit| ≤ 9 < 214748364), and pushes it onto result. The output equals the input. For example, x = 7 returns 7.

Zero

x = 0 is the degenerate case. The while (x != 0) condition is false from the start, so the loop body never executes and result stays 0. The function returns 0 immediately, which is correct.

Step 06

Full Annotated Code

class Solution {
    public int reverse(int x) {
        int result = 0;

        while (x != 0) {
            // Pop the last digit from x
            int digit = x % 10;
            x /= 10;

            // Check for positive overflow BEFORE it happens
            // If result > MAX/10, then result*10 would already overflow
            // If result == MAX/10 and digit > 7, then result*10+digit > MAX
            if (result > Integer.MAX_VALUE / 10 ||
                (result == Integer.MAX_VALUE / 10 && digit > 7))
                return 0;

            // Check for negative overflow (underflow)
            // If result < MIN/10, then result*10 would already underflow
            // If result == MIN/10 and digit < -8, then result*10+digit < MIN
            if (result < Integer.MIN_VALUE / 10 ||
                (result == Integer.MIN_VALUE / 10 && digit < -8))
                return 0;

            // Push the digit onto result
            result = result * 10 + digit;
        }

        return result;
    }
}

No long, no strings, no abs(). This solution handles positive and negative numbers uniformly, detects overflow using only 32-bit arithmetic, and runs in O(log10(x)) time with O(1) space. This is the optimal solution LeetCode expects.

Step 07

Interactive Demo

Enter any 32-bit integer and watch the algorithm pop and push digits one at a time, with live overflow detection.

Reverse Integer Visualizer


Step 08

Complexity Analysis

Time
O(log10 n)
Space
O(1)

The loop runs once per digit, and the number of digits in x is floor(log10(|x|)) + 1. Each iteration does O(1) work: one modulo (x % 10), one integer division (x / 10), two overflow comparisons, one multiply, and one add. No extra data structures are allocated — just a single result integer variable, giving O(1) space.

Approach Breakdown

STRING REVERSAL
O(log10 n) time
O(log10 n) space

Converts the integer to a character array of d = log10(n) digits, reverses the array in O(d), then parses it back. The character array and the reversed string each require O(d) memory. Still needs an overflow check before parsing.

MOD + DIV
O(log10 n) time
O(1) space

A while loop pops digits via x % 10 and pushes them onto the result via result * 10 + digit -- one digit per iteration for d total iterations. Overflow is detected before each multiply by comparing result against MAX_VALUE / 10. Only a single result integer is allocated.

🎯

The number of digits is log10(n), so reversing is logarithmic. For a 32-bit integer the loop runs at most 10 times, making the algorithm effectively O(1) in practice. The tricky part of this problem isn't the complexity — it's detecting overflow before it happens, using only 32-bit arithmetic and no larger data types.

Coach Notes

Common Mistakes

Review these before coding to avoid predictable interview regressions.

Overflow in intermediate arithmetic

Wrong move: Temporary multiplications exceed integer bounds.

Usually fails on: Large inputs wrap around unexpectedly.

Fix: Use wider types, modular arithmetic, or rearranged operations.