Understand
30-second explanation
Build the interview-ready mental model before comparing implementations.
Decide if an integer reads the same forwards and backwards — without converting to a string. Negatives are never palindromes (the leading minus has no trailing match), and any non-zero number ending in 0 fails too. The elegant answer reverses only the SECOND HALF of the number and compares it to the first half, so the reversed value never exceeds the original and overflow is impossible.
Interview contextWhat is testedWhere candidates slipHow to stand outExplore interview contextHide interview context
What's being tested
Whether you can manipulate a number digit-by-digit with `% 10` and `/ 10`, reason about overflow, and find the half-reversal optimization instead of the obvious full-reversal or string conversion.
Where candidates slip
Reversing the entire number and overflowing on inputs near INT_MAX, or forgetting that negatives and trailing-zero numbers can never be palindromes.
How to stand out
Knock out the negative and trailing-zero edge cases in one guard line, then reverse only half the digits using `x > rev` as the stop condition — and explain why that bound makes overflow impossible.
Choose
Compare the available approaches
Use constraints and trade-offs to select the route you can defend in an interview.
Interactive decision treeInteractiveChoose the right approachFirst decision previewIs integer x a palindrome?x < 0 or (x%10==0 and x!=0)?YesNoExplore the full treeCollapse the tree
Learn & trace
Build each solution step by step
Move from the core idea to a visual trace, implementation, proof, and edge cases.
Approach 1 of 2
Reverse the Whole Number
1Hint 1Explore hintHide hint
A palindrome equals its own reverse. Can you build the reverse of x using only arithmetic, then compare it to the original?
2Hint 2Explore hintHide hint
Peel digits off the right with `x % 10`, and push them onto a running `reversed` value with `reversed = reversed * 10 + digit`.
3Hint 3Explore hintHide hint
Keep a copy of the original (since the loop destroys x), reverse fully, then check `original == reversed`. But watch: a 10-digit reverse can exceed a 32-bit int.
A · Core idea
The most direct arithmetic reading of "is x a palindrome?" is "does x equal reverse(x)?". So build the full reverse digit-by-digit and compare.
How the digit peeling works. x % 10 extracts the last digit; x / 10 (integer division) chops it off. To grow the reversed number we shift its existing digits left by multiplying by 10, then drop the freshly peeled digit into the now-empty ones place: reversed = reversed * 10 + x % 10. Repeat until x becomes 0 and reversed holds the mirror image. Because the original x is consumed by the loop, we snapshot it into original up front so we have something to compare against at the end.
Why this is the natural first attempt — and its fatal flaw. It maps one-to-one onto the definition, which makes it easy to reason about. But it has a real bug on a 32-bit machine: the reverse of a valid int can be larger than INT_MAX. Take x = 1463847412 — a perfectly legal 32-bit int. Its reverse 2147483641... is fine, but x = 2147447412 reverses past the 2³¹−1 ceiling and overflows to a garbage negative number, producing a wrong answer (or undefined behavior in C/Java where ints wrap silently).
The mitigations and why they're unsatisfying. You can store the reverse in a 64-bit long to dodge overflow, but that quietly assumes a wider type is available and feels like papering over the real issue. The cleaner fix — the one interviewers want — is to never build a number bigger than half of x in the first place. That's the next approach.
B · Visual dry run
Interactive dry run
Select a frame to connect the decision with its visual state.
x = 121start
original = 121, reversed = 0
x = 121trueC · Code with teaching comments
Reference implementation previewpublic boolean isPalindrome(int x) { if (x < 0) { return false; } long reversed = 0;Explore the full codeHide the full code
D · Why it works and complexityO(log₁₀ n) timeO(1) spaceOpen the invariant and proofExplore the proofHide the proof
reversed = reversed * 10 + x % 10 is the universal 'reverse a number' idiom — memorize it. The catch nobody mentions until it bites them: reversing a full 32-bit int can overflow 32 bits, so either widen to long or, better, only reverse half.
ComplexityO(log₁₀ n) time, O(1) space — We process each of the ~log₁₀(n) digits once. Only a couple of integer variables are used, so O(1) space — but the reversed value can overflow 32 bits.
E · Edge cases and pitfalls5x = -121 — Negative guard returns false before any reversing.Explore edge casesHide edge cases
Edge cases handled
x = -121Negative guard returns false before any reversing.x = 2147447412 (Java int)Reversing in a 32-bit int overflows — this is exactly why we store reversed in a long, or switch to the half-reversal approach.
Pitfalls
- Reversing into an `int` instead of a `long` — overflows on large 32-bit inputs.
- Forgetting to snapshot the original before the loop destroys x.
- Not handling negatives — `-121 % 10` is language-dependent and can produce surprising signs.
Approach 2 of 2 · Optimal
Reverse Half the Number (Optimal)
1Hint 1Explore hintHide hint
You don't need the whole reverse — a palindrome's second half, reversed, equals its first half. Can you build only the reversed second half and stop halfway?
2Hint 2Explore hintHide hint
Peel digits into `reversed` while shrinking `x`. The natural stopping point is when `reversed` becomes ≥ `x`: at that moment you've consumed the right half and `x` holds the left half.
3Hint 3Explore hintHide hint
For even digit counts, compare `x == reversed`. For odd counts the middle digit ends up in `reversed`, so also accept `x == reversed / 10` (drop that middle digit).
A · Core idea
Instead of reversing the entire number and risking overflow, reverse only the second half and compare it to the first half. The two halves of a palindrome are mirror images, so the reversed second half should exactly equal the untouched first half.
The two guard clauses do real work. First, x < 0 → false, because a leading minus can never mirror. Second, x % 10 == 0 && x != 0 → false: a number ending in 0 would need to start with 0 to be symmetric, but integers have no leading zeros — so 10, 1230, 100 are all immediately disqualified. The lone exception is 0 itself, which is why the guard explicitly spares x != 0. Knocking these out up front keeps the main loop clean.
Why `while (x > reversed)` is the perfect stopping condition. Each iteration moves one digit from the right end of x onto reversed, so x shrinks and reversed grows. They cross exactly at the midpoint of the digits. When x becomes less than or equal to reversed, we've peeled off the entire right half — reversed is the reversed second half and x is the first half. Because we never push more than half the digits into reversed, its value is bounded by roughly √(original) in magnitude and cannot overflow, even for inputs hugging INT_MAX. That's the whole point of this approach.
Handling odd vs even digit counts. With an even count like 1221: the loop ends with x = 12, reversed = 12, and x == reversed → palindrome. With an odd count like 12321: the loop ends with x = 12, reversed = 123 — the middle digit 3 got swept into reversed. We don't care about the middle digit (it mirrors itself), so we strip it with integer division: reversed / 10 == 12 == x → palindrome. Accepting x == reversed || x == reversed / 10 covers both cases in one return.
B · Visual dry run
Interactive dry run
Select a frame to connect the decision with its visual state.
x = 1221Interactive diagram
Where the two halves meet
startx shrinks from the left, reversed grows from the right; they cross at the middle.
trueC · Code with teaching comments
D · Why it works and complexityO(log₁₀ n) timeO(1) spaceOpen the invariant and proofExplore the proofHide the proof
The stopping condition x > reversed is the elegant core: it self-terminates at the digit midpoint without ever counting the digits first, and it guarantees reversed stays small enough to never overflow. Reverse half, not the whole — that single idea is what separates the textbook answer from the interview-grade one.
ComplexityO(log₁₀ n) time, O(1) space — We process only half the ~log₁₀(n) digits, still O(log₁₀ n) time. `reversed` never exceeds half the digits of x, so it stays within range — provably no overflow, O(1) space.
E · Edge cases and pitfalls6x = 0 — Guard spares it (x != 0). Loop never runs (0 > 0 is false), returns 0 == 0 → true.Explore edge casesHide edge cases
Edge cases handled
x = 0Guard spares it (x != 0). Loop never runs (0 > 0 is false), returns 0 == 0 → true.x = 12321Odd length. Loop ends with x = 12, reversed = 123. x == reversed/10 → 12 == 12 → true.x = 10x % 10 == 0 and x != 0 → guard returns false immediately.
Pitfalls
- Forgetting the `reversed / 10` clause — breaks every odd-length palindrome like 12321.
- Dropping the `x != 0` part of the guard — would wrongly reject 0.
- Using `x >= reversed` instead of `x > reversed` — overshoots the midpoint on some inputs.
Practice
Try the solution yourself
Edit the optimal implementation, test another input, and observe the result.
Editable code previewpublic boolean isPalindrome(int x) { if (x < 0 || (x % 10 == 0 && x != 0)) { return false; } int reversed = 0;Explore the playgroundClose the playground
Avoid mistakes
Recognize the interview traps
Understand why common attempts fail before reviewing the corrected implementation.
1Overflow from reversing the whole number
On a 32-bit machine, reversing a valid int can exceed INT_MAX and wrap to garbage. Reverse only half, or use a 64-bit type.
Explore the code comparisonHide the code comparison
Overflow from reversing the whole number
On a 32-bit machine, reversing a valid int can exceed INT_MAX and wrap to garbage. Reverse only half, or use a 64-bit type.
Don't write this
int reversed = 0;
while (x != 0) {
reversed = reversed * 10 + x % 10; // can overflow int
x /= 10;
}Write this instead
int reversed = 0;
while (x > reversed) {
reversed = reversed * 10 + x % 10; // bounded to half → safe
x /= 10;
}2Missing the odd-length comparison
For odd digit counts the middle digit lands in `reversed`. Comparing only `x == reversed` rejects valid palindromes like 12321.
Explore the code comparisonHide the code comparison
Missing the odd-length comparison
For odd digit counts the middle digit lands in `reversed`. Comparing only `x == reversed` rejects valid palindromes like 12321.
Don't write this
return x == reversed_numWrite this instead
return x == reversed_num or x == reversed_num // 103Not disqualifying trailing-zero numbers
A non-zero number ending in 0 (10, 1230) can't be a palindrome. Without the guard the half-reversal logic still works, but stating the rule shows you understand leading-zero impossibility.
Explore the code comparisonHide the code comparison
Not disqualifying trailing-zero numbers
A non-zero number ending in 0 (10, 1230) can't be a palindrome. Without the guard the half-reversal logic still works, but stating the rule shows you understand leading-zero impossibility.
Don't write this
if (x < 0) {
return false;
}Write this instead
if (x < 0 || (x % 10 == 0 && x != 0)) {
return false;
}Revise
Carry the pattern into the interview
Pattern to remember
Reverse half the digits, compare to the other half
Code pattern to memorize
if x < 0 or (x % 10 == 0 and x != 0): return False
rev = 0
while x > rev:
rev = rev * 10 + x % 10
x //= 10
return x == rev or x == rev // 10Rules to remember
- 1Negatives are never palindromes —
-121reversed is121-, the minus sign has no partner. Return false immediately. - 2Any non-zero number ending in 0 fails — a palindrome can't start with 0, so
10,1230are out. Only0itself survives this rule. - 3Reverse only HALF the number — stop when the leftover
xis no longer greater than the reversedrev. This capsrevat half the digits, so it can never overflow even whenxis nearINT_MAX. - 4Handle odd digit counts by dropping the middle digit: compare
x == rev(even length) ORx == rev / 10(odd length, middle digit lives inrev). - 5Avoid the string trick if asked —
str(x) == str(x)[::-1]works but the interviewer is testing whether you can do it in pure arithmetic with O(1) space.
Use this pattern when
- Asked to test a numeric property (palindrome, digit pattern) without string conversion
- Need O(1) extra space — no array or string buffer allowed
- Overflow is a concern and you want to provably stay in range
- Working digit-by-digit with `% 10` and `/ 10` feels natural
Choose another pattern when
- String conversion is explicitly allowed → `str(x) == str(x)[::-1]` is two lines
- You need the actual reversed value (Reverse Integer) → reverse the whole thing and overflow-check
- Input is already a string / array of digits → two-pointer compare instead of arithmetic
- Arbitrary-precision / BigInteger input → digit array, not int math
Interview takeaway
Reversing only half the number is the trick that turns a potential-overflow problem into a clean O(1)-space comparison. The same 'meet in the middle of the digits' idea reappears in Reverse Integer and any 'is this number symmetric?' question — once you see why `x > rev` is the perfect stopping condition, you own this pattern.
Continue
Transfer the pattern to another problem
Use a direct variation or pattern sibling to prove the idea is reusable.
Transferable patternDigit manipulation with `% 10` and `/ 10`, plus the 'reverse only half to avoid overflow' trick. Recognise it whenever you must test a numeric symmetry without strings. The half-and-compare idea also drives Palindrome Linked List and any 'meet in the middle' check.
Practice queueDirect variations and pattern siblings
Direct follow-ups
- Reverse IntegerComing soonReverse the whole number — now overflow detection is the whole point, not avoidable.
- Palindrome Linked ListComing soonSame 'compare halves' idea — find the middle, reverse the second half, walk inward.
- Valid PalindromeComing soonString version — two pointers from both ends, skip non-alphanumerics.
- String to Integer (atoi)Coming soonDigit-by-digit accumulation with overflow clamping — same arithmetic muscles.