Topics › Basics › Know Basic Maths
Reverse a number
LeetCode ↗ Java source ↗ Edit this article ↗
Jump to code:
Problem
You are given a 32-bit signed integer n. Return the integer formed by writing the decimal digits of n in reverse order. The sign stays where it is: -123 becomes -321. Trailing zeros of the input become leading zeros of the output and therefore vanish: 120 becomes 21.
The LeetCode version (“Reverse Integer”) adds one rule: if the reversed value does not fit in a 32-bit signed integer, return 0, and you may not use 64-bit arithmetic to detect that. The TUF version only asks for the reversal. The code below handles both, and the optimal approach obeys the no-64-bit rule.
Constraints: -2^31 ≤ n ≤ 2^31 - 1.
Example 1
n = 123
answer = 321
Example 2
n = -120
answer = -21 // sign kept, trailing zero dropped
Example 3
n = 1534236469
answer = 0 // reversed it would be 9646324351, which exceeds 2^31 - 1
Approach 1: Brute force, via a string
Intuition. Reversing a sequence of characters is a solved problem: StringBuilder.reverse(). So write the absolute value as a string, reverse it, parse it back into a long, reapply the sign and check the range. Long.parseLong happily ignores leading zeros, so "021" parses as 21.
Algorithm.
- Let
abs = |n|as along(thelongmatters forInteger.MIN_VALUE). - Convert to a string, reverse, parse as
long. - Negate if
nwas negative. - If the result is outside
[Integer.MIN_VALUE, Integer.MAX_VALUE], return0; otherwise cast toint.
static int bruteForce(int n) {
long abs = Math.abs((long) n);
String reversed = new StringBuilder(Long.toString(abs)).reverse().toString();
long result = Long.parseLong(reversed);
if (n < 0) result = -result;
if (result < Integer.MIN_VALUE || result > Integer.MAX_VALUE) return 0;
return (int) result;
}
Complexity. Time O(d) for d digits. Space O(d) for the string and the builder.
Correct, but it dodges the arithmetic the problem is testing, and it would be disqualified by the LeetCode rule against 64-bit integers.
Approach 2: Better, digit by digit into a long
Intuition. n % 10 is the last digit and n / 10 is the number without it. If we read the digits last-to-first and keep appending each one to an accumulator with rev = rev * 10 + digit, the accumulator receives the digits in reverse order, which is exactly the reversed number. Trailing zeros of n are appended first, when rev is still 0, so 0 * 10 + 0 keeps rev at 0 and they disappear naturally.
We work on the absolute value in a long, so the reversal of any 10-digit input (at most 9,999,999,999) fits without overflow, and we compare with the int limits at the end.
Algorithm.
x = |n|as along,rev = 0.- While
x > 0:rev = rev * 10 + x % 10, thenx /= 10. - Negate
revifn < 0. - Return
0ifrevis outside theintrange, else(int) rev.
static int better(int n) {
long x = Math.abs((long) n);
long rev = 0;
while (x > 0) {
rev = rev * 10 + x % 10;
x /= 10;
}
if (n < 0) rev = -rev;
if (rev < Integer.MIN_VALUE || rev > Integer.MAX_VALUE) return 0;
return (int) rev;
}
Dry run on n = 123:
| x | x % 10 | rev after step |
|---|---|---|
| 123 | 3 | 3 |
| 12 | 2 | 32 |
| 1 | 1 | 321 |
| 0 | loop ends, return 321 |
Complexity. Time O(d). Space O(1).
This is the version to write when 64-bit integers are allowed; it is short and every line is obviously right.
Approach 3: Optimal, int only with an overflow guard
Intuition. Without a long, we must detect overflow before it happens. The step that can overflow is rev * 10 + digit. It is safe exactly when the new value stays in range, i.e. rev * 10 + digit ≤ 2147483647. Rearranged into checks that never overflow themselves:
- if
rev > 214748364(that isInteger.MAX_VALUE / 10), thenrev * 10alone is already too large; - if
rev == 214748364, thenrev * 10 = 2147483640and only digits0..7keep us under2147483647.
The mirror image holds for the negative side with Integer.MIN_VALUE / 10 = -214748364 and the digit bound -8.
A second trick removes all sign handling: in Java, % keeps the sign of the dividend and / truncates toward zero, so for negative n every digit is negative and rev is built as a negative number directly.
Algorithm.
rev = 0.- While
n != 0:digit = n % 10,n /= 10. - If appending
digitwould exceedInteger.MAX_VALUEor go belowInteger.MIN_VALUE(the two checks above), return0. rev = rev * 10 + digit.- Return
rev.
static int optimal(int n) {
int rev = 0;
while (n != 0) {
int digit = n % 10; // negative when n is negative, so the sign takes care of itself
n /= 10;
if (rev > Integer.MAX_VALUE / 10 || (rev == Integer.MAX_VALUE / 10 && digit > 7)) return 0;
if (rev < Integer.MIN_VALUE / 10 || (rev == Integer.MIN_VALUE / 10 && digit < -8)) return 0;
rev = rev * 10 + digit;
}
return rev;
}
Complexity. Time O(d), at most ten iterations for an int. Space O(1).
Why is the digit > 7 check actually redundant for valid inputs? If rev == 214748364 we have already consumed nine digits, so the input had ten digits and started with a 1 or 2 (anything larger exceeds 2^31 - 1), making the last digit appended at most 2. The check costs nothing and keeps the method correct for any caller, so leave it in.
Edge cases and pitfalls
- Overflow.
1534236469reversed is9646324351, far outsideint. Compute inlongand range-check (Approach 2), or guard before multiplying (Approach 3). Never computerev * 10 + digitinintand check afterwards, because the overflowed value is garbage that may happen to look valid. Integer.MIN_VALUE.Math.abs(-2147483648)as anintis still-2147483648. Cast tolongfirst. Approach 3 avoids the issue by never negating.- Trailing zeros.
120 -> 21,1000000000 -> 1. No special code is needed; appending a0to an accumulator that is still0does nothing. - Zero and single digits.
0 -> 0,7 -> 7. The loops run zero or one time. - Negative sign. Keep it. Either strip it, reverse the magnitude and restore it (Approaches 1 and 2), or let Java’s signed
%carry it through (Approach 3). - Largest reversible input.
1463847412reverses to2147483641, which still fits. Its neighbour1534236469does not. Both are in the tests.
Related problems
- Count all Digits of a Number is the same
% 10loop with a counter instead of an accumulator. - Palindrome Number reverses a number and compares it with the original, with a half-reversal trick to avoid overflow.
- Check if the Number is Armstrong combines digit extraction with a digit count.