Problem Walkthrough

Palindrome Number LeetCode 9 Deep Dive

A complete walkthrough of LeetCode 9 Palindrome Number using the reverse-half strategy — instead of reversing all digits (which risks 32-bit overflow), reverse only the second half of the number digit by digit and compare it with the remaining first half; when the reversed half is greater than or equal to what remains of x, you have processed half the digits and can compare directly without any string conversion.

7 min read|

Palindrome Number

LeetCode 9

Problem Overview

LeetCode 9 — Palindrome Number — gives you an integer x and asks you to return true if x is a palindrome, and false otherwise. A palindrome reads the same forwards and backwards: 121 is a palindrome, -121 is not (it reads -121 forward but 121- backward), and 10 is not (it reads 01 backward, and integers do not have leading zeros). The problem includes a follow-up: can you solve it without converting the integer to a string?

The examples cover the key cases: 121 returns true, -121 returns false, and 10 returns false. The constraint is that x is a 32-bit signed integer, so -2^31 <= x <= 2^31-1. The string-based approach is trivially correct but the follow-up pushes you toward the mathematically elegant reverse-half solution that demonstrates deep understanding of digit manipulation.

Understanding why certain integers are immediate rejects is the first step. Negative numbers always have a leading minus sign which makes them non-palindromes by definition — the digit sequence of a negative number cannot read the same forwards and backwards because the minus appears only at the front. Numbers ending in zero (except zero itself) cannot be palindromes because no integer starts with a leading zero.

  • Given integer x, return true if x is a palindrome, false otherwise
  • 121 → true, -121 → false, 10 → false
  • Constraints: -2^31 <= x <= 2^31 - 1
  • A palindrome reads the same forwards and backwards
  • Follow-up: solve it without converting the integer to a string

Quick Rejects

Before doing any digit reversal, two quick checks eliminate a large fraction of inputs in O(1). First: if x is negative, return false immediately. A negative number has a leading minus sign, so it cannot be a palindrome — the digit sequence starting from the left begins with minus, but from the right it ends with a digit, so they can never match.

Second: if x ends in zero and x is not zero itself, return false. If the last digit of x is 0, then for x to be a palindrome its first digit would also have to be 0 — but integers do not have leading zeros. The only exception is x == 0 itself, which is a palindrome. The check is: if x != 0 and x % 10 == 0, return false.

Together these two checks — negative and trailing-zero rejects — eliminate all negative numbers and all positive multiples of 10 (10, 20, 100, 1000, etc.) in constant time before any digit processing begins. This is not just an optimization; it also simplifies the main loop by guaranteeing that x is positive and its last digit is nonzero.

💡

Early Rejects Handle ~50% of Inputs in O(1)

Eliminating negatives (x < 0) and trailing-zero numbers (x % 10 == 0 and x != 0) immediately handles roughly half of all integer inputs in O(1) before any digit processing. Negatives are never palindromes due to the minus sign; numbers ending in zero cannot be palindromes because no integer starts with a leading zero. These two checks are free and should always be applied first.

Reverse Half Strategy

The naive approach — reverse all digits of x and compare to the original — risks 32-bit integer overflow if the reversed number is large. For example, reversing 2147483647 (INT_MAX) gives 7463847412, which overflows a 32-bit signed integer. The reverse-half strategy avoids this entirely by reversing only the second half of the number and comparing it to the first half.

The algorithm pops digits from the right of x one at a time using the same pop-and-push technique from Reverse Integer (LeetCode 7): pop the last digit with x % 10, remove it from x with integer division x = x / 10, push it onto the reversed half with reversedHalf = reversedHalf * 10 + digit. Repeat until the reversed half is greater than or equal to the remaining x.

When reversedHalf >= x, the loop stops because we have processed half the digits (or more in the case of an odd-length number where the middle digit ends up in reversedHalf). The comparison then determines if x is a palindrome.

  1. 1Apply quick rejects: if x < 0 or (x % 10 == 0 and x != 0), return false
  2. 2Initialize reversedHalf = 0
  3. 3While x > reversedHalf: pop last digit of x (digit = x % 10), remove from x (x = x / 10), push to reversedHalf (reversedHalf = reversedHalf * 10 + digit)
  4. 4Loop exits when reversedHalf >= x — we have reversed half the digits
  5. 5For even-length numbers: check x == reversedHalf
  6. 6For odd-length numbers: check x == reversedHalf / 10 (discard middle digit from reversedHalf)

How to Know When Half Is Done

The loop condition x > reversedHalf elegantly signals when half the digits have been processed. At the start, x holds all digits and reversedHalf is 0. Each iteration moves one digit from x to reversedHalf. When reversedHalf catches up to x — i.e., reversedHalf >= x — exactly half the digits (rounded up for odd-length) have been moved.

For even-digit palindromes like 1221: after two iterations x = 12 and reversedHalf = 12. The condition x > reversedHalf is false (12 > 12 is false), so the loop exits. The palindrome check is x == reversedHalf, i.e., 12 == 12 → true. For odd-digit palindromes like 12321: after two iterations x = 12 and reversedHalf = 123. The loop exits because 12 > 123 is false. The middle digit (3, the ones digit of 123) is irrelevant, so we check x == reversedHalf / 10, i.e., 12 == 12 → true.

This works because a palindrome by definition has a symmetric first and second half. By reversing the second half and comparing to the first half, we verify symmetry at the digit level without ever computing the full reversal. The middle digit of an odd-length palindrome can be anything — it pairs with itself — so dividing reversedHalf by 10 strips it cleanly.

ℹ️

Reversing Half Avoids Overflow

Reversing only the second half of x avoids the overflow problem of full reversal. The reversed half is at most half the magnitude of the original number, so it always fits comfortably within 32-bit bounds for any valid 32-bit input. This is why we compare reversedHalf >= x rather than reversing all digits — the half is guaranteed to be smaller than or equal to x when the loop starts, and when it surpasses x we know we are done.

Walk-Through: 12321

Start: x = 12321, reversedHalf = 0. Is x > reversedHalf? 12321 > 0 → yes. Pop last digit: digit = 12321 % 10 = 1. Remove from x: x = 12321 / 10 = 1232. Push to reversed: reversedHalf = 0 * 10 + 1 = 1. State: x = 1232, reversedHalf = 1.

Is x > reversedHalf? 1232 > 1 → yes. Pop: digit = 1232 % 10 = 2. Remove: x = 1232 / 10 = 123. Push: reversedHalf = 1 * 10 + 2 = 12. State: x = 123, reversedHalf = 12.

Is x > reversedHalf? 123 > 12 → yes. Pop: digit = 123 % 10 = 3. Remove: x = 123 / 10 = 12. Push: reversedHalf = 12 * 10 + 3 = 123. State: x = 12, reversedHalf = 123. Is x > reversedHalf? 12 > 123 → no. Loop exits. Odd-length check: x == reversedHalf / 10 → 12 == 123 / 10 → 12 == 12 → true. Answer: true.

  1. 1x=12321, rev=0: 12321>0 → pop 1, x=1232, rev=1
  2. 2x=1232, rev=1: 1232>1 → pop 2, x=123, rev=12
  3. 3x=123, rev=12: 123>12 → pop 3, x=12, rev=123
  4. 4x=12, rev=123: 12>123 is false → loop exits
  5. 5Odd-length check: x == rev/10 → 12 == 12 → true

Code Walkthrough — Python and Java

Python implementation: def isPalindrome(self, x: int) -> bool: if x < 0 or (x % 10 == 0 and x != 0): return False; reversed_half = 0; while x > reversed_half: reversed_half = reversed_half * 10 + x % 10; x //= 10; return x == reversed_half or x == reversed_half // 10. The floor division //= ensures x stays an integer as digits are removed. The final return handles both even (x == reversed_half) and odd (x == reversed_half // 10) length numbers in a single expression.

Java implementation: public boolean isPalindrome(int x) { if (x < 0 || (x % 10 == 0 && x != 0)) return false; int reversedHalf = 0; while (x > reversedHalf) { reversedHalf = reversedHalf * 10 + x % 10; x /= 10; } return x == reversedHalf || x == reversedHalf / 10; } Java integer division truncates toward zero, so x /= 10 and reversedHalf / 10 both behave correctly for positive integers. No overflow risk because reversedHalf is always at most half the original magnitude.

Both implementations run in O(log10(n)) time — there are exactly as many loop iterations as half the digit count of x — and use O(1) extra space. No strings, arrays, or auxiliary data structures. The time complexity is technically O(log10(n) / 2) but simplifies to O(log n). The space complexity is O(1) regardless of input magnitude.

⚠️

The String Approach Violates the Follow-Up

The string conversion approach — str(x) == str(x)[::-1] in Python or String.valueOf(x).equals(new StringBuilder(String.valueOf(x)).reverse().toString()) in Java — is trivially correct but violates the follow-up constraint of solving without string conversion. Interviewers asking LeetCode 9 almost always expect the math-based reverse-half approach. Using string conversion may be accepted by the judge but will likely disappoint in a real interview.

Ready to master algorithm patterns?

YeetCode flashcards help you build pattern recognition through active recall and spaced repetition.

Start practicing now