7. Reverse Integer (Medium)
Problem
Given a signed 32-bit integer x, return x with its digits reversed. If reversing causes the value to go outside the signed 32-bit range [-2³¹, 2³¹ − 1], return 0.
You are not allowed to store 64-bit integers.
Example
x = 123→321x = -123→-321x = 120→21
LeetCode 7 · Link · Medium
Try it yourself
Starter code: this editor begins with intentional TODOs. Fill the function, run the embedded tests, then compare your solution with the worked approaches below.
Click Run Python to execute. First run downloads Python (~10 MB, cached after that).
Starter code: this editor begins with intentional TODOs. Fill the function, run the embedded tests, then compare your solution with the worked approaches below.
Click Run TS to execute. First run downloads Babel (~400 KB, cached after that).
Starter code: this editor begins with intentional TODOs. Fill the function, run the embedded tests, then compare your solution with the worked approaches below.
Click Run Go to execute. Runs via the Go Playground API.
Approach 1: String manipulation
Convert to string, reverse, handle sign; check range.
def reverse(x): sign = -1 if x < 0 else 1 # L1: O(1) rev = int(str(abs(x))[::-1]) * sign # L2: O(log|x|) string ops return 0 if rev < -2**31 or rev > 2**31 - 1 else rev # L3: O(1)function reverse(x: number): number { const sign = x < 0 ? -1 : 1; // L1: O(1) const rev = parseInt(String(Math.abs(x)).split('').reverse().join('')) * sign; // L2: O(log|x|) const INT_MIN = -(2 ** 31), INT_MAX = 2 ** 31 - 1; return rev < INT_MIN || rev > INT_MAX ? 0 : rev; // L3: O(1)}import ( "strconv")
func reverse(x int) int { sign := 1 if x < 0 { sign = -1 x = -x } s := strconv.Itoa(x) // L2: O(log|x|) string ops runes := []rune(s) for i, j := 0, len(runes)-1; i < j; i, j = i+1, j-1 { runes[i], runes[j] = runes[j], runes[i] } rev, _ := strconv.Atoi(string(runes)) rev *= sign if rev < -1<<31 || rev > 1<<31-1 { // L3: O(1) return 0 } return rev}final class Solution { func reverse(_ x: Int) -> Int { let sign = x < 0 ? -1 : 1 let digits = String(String(abs(x)).reversed()) let value = sign * (Int(digits) ?? 0) let lowerBound = Int(Int32.min) let upperBound = Int(Int32.max) return (lowerBound...upperBound).contains(value) ? value : 0 }}Where the time goes, line by line
Variables: d = number of digits in x, d = .
| Line | Per-call cost | Times executed | Contribution |
|---|---|---|---|
| L1 (sign check) | 1 | ||
| L2 (string reverse) | 1 | ← dominates | |
| L3 (range check) | 1 |
Complexity
- Time: , driven by L2 (string conversion and reversal over all digits).
- Space: for the reversed string.
Easy, but uses language features that dodge the “no 64-bit int” constraint.
Approach 2: Digit extraction with overflow check (canonical)
Pop the last digit with x % 10 and append to a reversed number, checking for overflow before the push.
INT_MIN = -2**31INT_MAX = 2**31 - 1
def reverse(x): sign = -1 if x < 0 else 1 # L1: O(1) x = abs(x) # L2: O(1) result = 0 while x: # L3: loop d times (d = digits) digit = x % 10 # L4: O(1) x //= 10 # L5: O(1) # pre-check overflow under the target sign if sign == 1 and (result > INT_MAX // 10 or (result == INT_MAX // 10 and digit > 7)): return 0 # L6: O(1) overflow guard if sign == -1 and (result > -INT_MIN // 10 or (result == -INT_MIN // 10 and digit > 8)): return 0 # L7: O(1) overflow guard result = result * 10 + digit # L8: O(1) return sign * resultconst INT_MIN = -(2 ** 31);const INT_MAX = 2 ** 31 - 1;
function reverse(x: number): number { const sign = x < 0 ? -1 : 1; // L1: O(1) x = Math.abs(x); // L2: O(1) let result = 0; while (x) { // L3: loop d times (d = digits) const digit = x % 10; // L4: O(1) x = Math.floor(x / 10); // L5: O(1) if (sign === 1 && (result > Math.floor(INT_MAX / 10) || (result === Math.floor(INT_MAX / 10) && digit > 7))) return 0; // L6: O(1) overflow guard if (sign === -1 && (result > Math.floor(-INT_MIN / 10) || (result === Math.floor(-INT_MIN / 10) && digit > 8))) return 0; // L7: O(1) overflow guard result = result * 10 + digit; // L8: O(1) } return sign * result;}const intMin = -1 << 31const intMax = 1<<31 - 1
func reverse(x int) int { sign := 1 if x < 0 { sign = -1 x = -x } result := 0 for x != 0 { // L3: loop d times (d = digits) digit := x % 10 // L4: O(1) x /= 10 // L5: O(1) if sign == 1 && (result > intMax/10 || (result == intMax/10 && digit > 7)) { return 0 // L6: O(1) overflow guard } if sign == -1 && (result > (-intMin)/10 || (result == (-intMin)/10 && digit > 8)) { return 0 // L7: O(1) overflow guard } result = result*10 + digit // L8: O(1) } return sign * result}final class Solution { func reverse(_ x: Int) -> Int { let sign = x < 0 ? -1 : 1 let limit = sign > 0 ? Int(Int32.max) : Int(Int32.max) + 1 var remaining = abs(x) var result = 0
while remaining != 0 { let digit = remaining % 10 remaining /= 10 if result > (limit - digit) / 10 { return 0 } result = result * 10 + digit }
return sign * result }}Where the time goes, line by line
Variables: d = number of digits in x, d = .
| Line | Per-call cost | Times executed | Contribution |
|---|---|---|---|
| L1-L2 (init) | 1 | ||
| L3-L8 (digit loop) | d | ← dominates | |
| L4-L5 (pop digit) | d | ||
| L6-L7 (overflow guard) | d | ||
| L8 (build result) | d |
One iteration per digit; each iteration does work.
Complexity
- Time: , driven by L3/L4-L8 (one loop iteration per digit).
- Space: .
Why the overflow check is tricky
INT_MAX = 2147483647. Before a push we need result * 10 + digit ≤ INT_MAX, i.e., result < INT_MAX / 10 (then any digit is fine) or result == INT_MAX / 10 = 214748364 and digit ≤ 7. Symmetric condition for negatives (where -INT_MIN = 2147483648 has last digit 8).
Try this approach:
Click Run Python to execute. First run downloads Python (~10 MB, cached after that).
Click Run TS to execute. First run downloads Babel (~400 KB, cached after that).
Click Run Go to execute. Runs via the Go Playground API.
Approach 3: Simpler check by computing and comparing
If your language allows a 64-bit intermediate (Python always does), you can compute the reversed value and then compare with bounds. Python-only; defeats the purpose of the constraint, but often acceptable in interviews if you articulate the simulated bound.
def reverse(x): sign = -1 if x < 0 else 1 rev = sign * int(str(abs(x))[::-1]) if rev < -2**31 or rev > 2**31 - 1: return 0 return revTry this approach:
final class Solution { func reverse(_ x: Int) -> Int { let sign = x < 0 ? -1 : 1 var remaining = abs(x) var result = 0
while remaining != 0 { result = result * 10 + remaining % 10 remaining /= 10 }
result *= sign let lowerBound = Int(Int32.min) let upperBound = Int(Int32.max) return (lowerBound...upperBound).contains(result) ? result : 0 }}Swift notes
Swift’s Int is 64-bit on the catalog runner, but the problem contract is signed 32-bit. The canonical approach checks the Int32 bounds before appending each digit, so its correctness does not depend on a wider intermediate. String reversal allocates storage for the digits and is useful only as the simpler baseline.
Summary
| Approach | Time | Space | Notes |
|---|---|---|---|
| String manipulation | Shortest | ||
| Digit extraction + pre-check | Language-agnostic | ||
| Compute then compare | Needs 64-bit intermediate |
The digit-extraction version with pre-push overflow check is the canonical interview answer, it proves you can reason about bounds under fixed-width arithmetic.
Test cases
# Quick smoke tests, paste into a REPL or save as test_007.py and run.# Uses the canonical implementation (Approach 2: digit extraction + pre-check).
INT_MIN = -2**31INT_MAX = 2**31 - 1
def reverse(x): sign = -1 if x < 0 else 1 x = abs(x) result = 0 while x: digit = x % 10 x //= 10 if sign == 1 and (result > INT_MAX // 10 or (result == INT_MAX // 10 and digit > 7)): return 0 if sign == -1 and (result > -INT_MIN // 10 or (result == -INT_MIN // 10 and digit > 8)): return 0 result = result * 10 + digit return sign * result
def _run_tests(): assert reverse(123) == 321 assert reverse(-123) == -321 assert reverse(120) == 21 assert reverse(0) == 0 assert reverse(2**31 - 1) == 0 # MAX_INT reversed overflows assert reverse(1534236469) == 0 # overflows after reversal print("all tests pass")
if __name__ == "__main__": _run_tests()const INT_MIN = -(2 ** 31);const INT_MAX = 2 ** 31 - 1;
function reverse(x: number): number { const sign = x < 0 ? -1 : 1; x = Math.abs(x); let result = 0; while (x) { const digit = x % 10; x = Math.floor(x / 10); if (sign === 1 && (result > Math.floor(INT_MAX / 10) || (result === Math.floor(INT_MAX / 10) && digit > 7))) return 0; if (sign === -1 && (result > Math.floor(-INT_MIN / 10) || (result === Math.floor(-INT_MIN / 10) && digit > 8))) return 0; result = result * 10 + digit; } return sign * result;}
console.assert(reverse(123) === 321);console.assert(reverse(-123) === -321);console.assert(reverse(120) === 21);console.assert(reverse(0) === 0);console.assert(reverse(2 ** 31 - 1) === 0);console.assert(reverse(1534236469) === 0);console.log("all tests pass");func reverse(x int) int { const intMin = -1 << 31 const intMax = 1<<31 - 1 sign := 1 if x < 0 { sign = -1 x = -x } result := 0 for x != 0 { digit := x % 10 x /= 10 if sign == 1 && (result > intMax/10 || (result == intMax/10 && digit > 7)) { return 0 } if sign == -1 && (result > (-intMin)/10 || (result == (-intMin)/10 && digit > 8)) { return 0 } result = result*10 + digit } return sign * result}Related data structures
- None.
Related concepts
- Math and Number Theory, the arithmetic invariant behind digits, divisibility, modulo behavior, and identities.
- Simulation, the explicit state model for executing rules exactly while keeping cases organized.