7. Reverse Integer

Reverse the digits of a 32-bit signed integer — but return 0 if the result would overflow. The trick is to check for overflow before you multiply, so you never need a 64-bit intermediate.

MediumMath32-bit OverflowDigit ManipulationTypeScript

PROBLEM What we're solving

Given a 32-bit signed integer x, return its digits reversed. If the reversed value falls outside the 32-bit signed range [-2 147 483 648, 2 147 483 647], return 0. Example: x = 123 321. Example: x = -120 -21 (trailing zeros vanish). Example: x = 15342364690 because reversing overflows.

KEY IDEA Pop a digit, push it, but check overflow first

Insight → treat the integer as a stream of digits: repeatedly pop the last digit via x % 10 and push it onto a running result via result * 10 + digit. The only wrinkle is overflow — and the fix is to check before the multiply: result > (INT_MAX - digit) / 10 tells you if the next push would overflow, without ever computing the overflowed value.

RECIPE Pop, overflow-check, push — repeat

  • 0 · Initialise. Set result = 0. Fix the 32-bit bounds as constants.
  • 1 · Pop the last digit. digit = x % 10; then x = Math.trunc(x / 10). In JavaScript, % preserves sign, so -123 % 10 === -3 — which is exactly what we want for negative numbers.
  • 2 · Check overflow BEFORE multiplying. If result > (INT_MAX - digit) / 10, the next push would exceed INT_MAX → return 0. Mirror the check for INT_MIN.
  • 3 · Push the digit. result = result * 10 + digit. We only reach here if the overflow check passed.
  • 4 · Repeat until x === 0.
Classic confusion → people try to detect overflow after multiplying — writing something like if ((result * 10 + digit) > INT_MAX) return 0. In JavaScript this seems to work (JS numbers are 64-bit floats), but it silently fails for very large inputs where the float loses integer precision. Always check before the multiply using the rearranged inequality result > (INT_MAX - digit) / 10.

COST Complexity & alternatives

String reversal
O(d)
Convert to string, reverse, parse back. Extra string allocation, and overflow detection is clunky.
Math pop/push
O(d)
O(d) time (d = number of digits ≤ 10), O(1) space. Overflow is caught cleanly before each step.

Both approaches are O(d) where d is the number of digits (at most 10 for a 32-bit int). The math approach wins on space and overflow correctness.

Pattern transfer →the “pop a digit, act on it, push it elsewhere” pattern recurs in Palindrome Number (reverse only the second half), Digit DP problems (iterate digits left-to-right building a bound), and Add Binary / Add Strings (process digit-by-digit with carry). The overflow check before multiply also appears in String to Integer (atoi).

RUN IT Pop last digit, push into result, check overflow first

step 0 / 7
STARTInput: 123. We will pop digits from the right and push them into the result, checking 32-bit overflow before each multiply.
1function reverse(x: number): number {
2 const INT_MAX = 2_147_483_647; // 2^31 - 1
3 const INT_MIN = -2_147_483_648; // -2^31
4
5 let result = 0;
6
7 while (x !== 0) {
8 const digit = x % 10; // pop last digit (negative-safe in JS)
9 x = Math.trunc(x / 10); // drop last digit
10
11 // Check overflow BEFORE multiplying — avoids 64-bit integer issues
12 if (result > Math.trunc((INT_MAX - digit) / 10)) return 0;
13 if (result < Math.trunc((INT_MIN - digit) / 10)) return 0;
14
15 result = result * 10 + digit; // push digit
16 }
17
18 return result;
19}
State
123
x (remaining)
0
result
digit
overflow?
active / remainingresult accumulatingdigit placed safelyoverflow — return 0
slowfast

TYPESCRIPT The solution, annotated

reverseInteger.ts
function reverse(x: number): number {
  const INT_MAX = 2_147_483_647;   //  2^31 - 1
  const INT_MIN = -2_147_483_648;  // -2^31

  let result = 0;

  while (x !== 0) {
    const digit = x % 10;          // pop last digit (negative-safe in JS)
    x = Math.trunc(x / 10);        // drop last digit

    // Check overflow BEFORE multiplying — avoids 64-bit integer issues
    if (result > Math.trunc((INT_MAX - digit) / 10)) return 0;
    if (result < Math.trunc((INT_MIN - digit) / 10)) return 0;

    result = result * 10 + digit;  // push digit
  }

  return result;
}

Reading it block by block

Lines 2–3 — constants. Hard-code INT_MAX = 2_147_483_647 and INT_MIN = -2_147_483_648. These are the 32-bit signed bounds the problem uses regardless of the host language's native integer width.
Lines 7–8 — pop the last digit. x % 10 extracts the last digit; sign follows x in JavaScript. Math.trunc(x / 10) drops it (not Math.floor, which would misbehave on negatives).
Lines 11–12 — overflow check BEFORE the multiply. Rearrange result * 10 + digit > INT_MAX into result > (INT_MAX - digit) / 10 to avoid computing the potentially overflowed value. The same rearrangement handles the negative side with INT_MIN.
Line 14 — push the digit. result = result * 10 + digit shifts the existing digits left by one decimal place and appends the new one. We only reach this line if overflow is impossible.
Line 18 — return. When x reaches 0we've processed every digit. result holds the fully reversed integer.
Complexity → O(d) time where d = number of digits (≤ 10 for a 32-bit int) — effectively O(1). O(1) space; no strings or arrays needed.

INTERVIEWFollow-ups they'll ask

  • “What if the input is a 64-bit integer?” Extend the bounds to Number.MAX_SAFE_INTEGER or use BigInt; the pop/push pattern is unchanged.
  • “Can you do it without the overflow pre-check?” In TypeScript you could stringify, reverse, and parse — but then you need isNaNand sign handling; it's messier.
  • “Why not just convert to a string?” It works, but the math approach is O(1) space, handles sign naturally, and demonstrates the pre-check overflow idiom that reappears in atoi and integer-arithmetic problems.
  • “What about palindrome detection?” LeetCode 9 (Palindrome Number) extends this: reverse only the second half of the number and compare — avoiding full reversal and thus the overflow concern entirely.
  • “Edge cases?” x = 00 (loop never runs). x = -120-21 (trailing zero vanishes). x = 1_534_236_469 0 (overflow).

MNEMONIC The one-liner

"Pop the last digit, peek at overflow BEFORE you push — if the door won't fit, return zero."

TRIGGERS When you see ___ → reach for ___

reverse digits of an integerx % 10 pop, result * 10 + digit push
32-bit overflow without BigIntpre-check: result > (INT_MAX - digit) / 10
palindrome number / half-reversesame pop/push, stop at midpoint
string-to-integer with overflow (atoi)same pre-multiply overflow check

SKELETON The reusable shape

skeleton.ts
function reverse(x: number): number {
  const INT_MAX = 2_147_483_647;
  const INT_MIN = -2_147_483_648;
  let result = 0;
  while (x !== 0) {
    const digit = x % 10;
    x = Math.trunc(x / 10);
    if (result > Math.trunc((INT_MAX - digit) / 10)) return 0;
    if (result < Math.trunc((INT_MIN - digit) / 10)) return 0;
    result = result * 10 + digit;
  }
  return result;
}

FLASHCARDS Tap to flip

How do you pop the last digit of an integer?
digit = x % 10; then drop it with x = Math.trunc(x / 10).
tap to flip
1 / 7
Answer to reveal explanations. No penalty for retries.Score: 0 / 9
QUESTION 01
What is the correct time complexity of the pop/push approach?
QUESTION 02
Trace x = 123. After all iterations, what is result?
QUESTION 03
Why must the overflow check happen BEFORE the multiply?
QUESTION 04
What does -120 % 10 equal in JavaScript?
QUESTION 05
Given x = 1_534_236_469, what should the function return?
QUESTION 06
Why use Math.trunc(x / 10) instead of Math.floor(x / 10)?
QUESTION 07
What is the space complexity of the math pop/push approach?
QUESTION 08
#7 · Reverse IntegerPop digits from x with mod/divide and push onto the result with ×10, checking for 32-bit signed overflow before each push. Return 0 immediately on overflow.Which algorithmic approach does this primarily use?
QUESTION 09
#7 · Reverse IntegerPop digits from x with mod/divide and push onto the result with ×10, checking for 32-bit signed overflow before each push. Return 0 immediately on overflow.Which implementation correctly solves it?