Given a signed 32-bit integer x, return x with its digits reversed. The sign is preserved, so reversing a negative number stays negative.
If reversing x produces a value that falls outside the signed 32-bit range [-2^31, 2^31 - 1], return 0 instead. Solve it without relying on 64-bit integer support.
Example
Reversing the digits of 123 gives 321.
Constraints
- -2^31 <= x <= 2^31 - 1
Intuition
A first pass converts x to a string, reverses the characters, and parses the result back into a number — leaning on the fact that a JavaScript number can briefly hold a value far outside the signed 32-bit range while we check it.
function reverse(x) {
// Remember the sign separately; we only reverse the digits of the magnitude.
const sign = x < 0 ? -1 : 1;
const digits = Math.abs(x).toString(); // e.g. -123 -> "123"
const reversedDigits = digits.split('').reverse().join(''); // "123" -> "321"
// parseInt drops any leading zeros that appear after reversing, e.g. "021" -> 21.
const result = sign * parseInt(reversedDigits, 10);
// Only now, after the *whole* reversed number already exists, do we check that it fits in 32 bits.
if (result < -(2 ** 31) || result > 2 ** 31 - 1) return 0;
return result;
}This works, but it leans on a string round-trip and on the reversed number briefly existing in full, outside the 32-bit range, before we ever check it — exactly the "64-bit integer support" the problem statement tells us not to rely on. Can we do better?
Notice we don't need the whole reversed number before we can tell it's too big: once result folds in a digit and crosses the bound, it will only grow further out of range as more digits are folded in — so the overflow can be caught while the number is being rebuilt, one digit at a time.
That's the same digit-by-digit discipline behind most Math & geometry problems: peel a digit off with % 10, shrink x with integer division, and push the digit onto an accumulator with result * 10 + digit — long division, run in reverse. Checking the running result against [-2^31, 2^31 - 1] after every push means the function can bail out the instant it goes out of range, and never needs to hold a value wider than 32 bits to notice.
One more simplification falls out for free: JavaScript's % keeps the sign of its left operand, so a negative x peels off negative digits and reverses straight into a negative result — no separate sign bookkeeping like the string version above needed.
Walking it through:
x = 6423 — peeling digits from the ones place and rebuilding result
Pop the ones digit off with x % 10 and push it onto result.
x shrinks to 64 (integer-divide away the digit just consumed); repeat.
Every push is checked against ±(2^31 − 1) — still nowhere close to the bound.
x is now 0, so this was the last digit.
Every digit has migrated from x into result, in reversed order.
x = 2147483645 — the same peel, but the last digit tips result over the 32-bit ceiling
Peeling starts from the ones digit, same as before.
Building up steadily — nothing so far is close to the 2^31 − 1 ceiling.
Nine digits folded in, result is still a 9-digit number — comfortably inside range, and every check so far has passed.
One digit left — the leading 2 of the original number.
The last digit tips the rebuilt number past the signed 32-bit ceiling. The guard catches it on the spot and returns 0 instead of the (wrong, oversized) reversed value.
Optimization
Digit-by-digit with overflow guard
Pop the last digit off x with % 10 and push it onto the accumulator with result * 10 + digit, repeating until x is exhausted. JavaScript's % keeps the sign of the dividend, so a negative input reverses straight into a negative result without special-casing the sign.
After each push, check whether result has left the signed 32-bit range; if so the true reversed value can't fit, so return 0. The guard runs before any further digits are appended, so it catches the overflow at the step it happens.
O(d) time where d is the digit count (at most 10), O(1) space.
function reverse(x) {
// Signed 32-bit bounds the rebuilt number must never cross.
const MIN = -(2 ** 31);
const MAX = 2 ** 31 - 1;
let result = 0;
while (x !== 0) {
// Peel off the last digit; JS's % keeps the sign of x, so negatives reverse correctly for free.
const digit = x % 10;
// Drop that digit from x (exact division since digit was the remainder).
x = (x - digit) / 10;
// Push the digit onto the front of the rebuilt (reversed) number.
result = result * 10 + digit;
// Bail out the instant the running result leaves the 32-bit range.
if (result < MIN || result > MAX) return 0;
}
return result;
}Complexity analysis
Time complexity: O(d), where d is the number of decimal digits in x. Here's why:
- The
whileloop runs once per digit: each iteration does O(1) work — a% 10, an integer division, and a bound check. - A signed 32-bit integer has at most 10 decimal digits, so the loop runs at most 10 times no matter how large
xgets within that range.
So the time is O(d) — and since d is bounded by the fixed 32-bit input width, it's effectively O(1) for this problem.
Space complexity: O(1). Here's why:
- Only a fixed handful of scalars are kept —
result,digit, and the two bound constants — regardless of how many digitsxhas. - Unlike the brute-force string version, no intermediate string or array is ever built.
So the extra space is O(1), not counting the input and output integers themselves.
Test cases
Beyond the example above, these are worth thinking through before you submit.
| Input | Expected output | Description |
|---|---|---|
| x = 0 | 0 | Zero reverses to itself — the loop body never runs. |
| x = 5 | 5 | A single digit has nothing to reverse. |
| x = -45 | -54 | Negative input — JS's sign-preserving % carries the sign through without extra bookkeeping. |
| x = 1200 | 21 | Two trailing zeros in x become leading zeros after reversal, and integer arithmetic drops them for free. |
| x = 5555 | 5555 | All digits identical — the rebuilt number matches the input exactly. |
| x = -2147483642 | 0 | Reverses to -2463847412, past the signed 32-bit floor of -2^31 — the guard fires and returns 0. |
Try it yourself
Write your solution against the real judge before checking the reference.