#9 - Palindrome Number
Palindrome Number
- Difficulty: Easy
- Topics: Math
- Link: https://leetcode.com/problems/palindrome-number/
Problem Description
Given an integer x, return true if x is a palindrome*, and* false otherwise.
Example 1:
Input: x = 121
Output: true
Explanation: 121 reads as 121 from left to right and from right to left.
Example 2:
Input: x = -121
Output: false
Explanation: From left to right, it reads -121. From right to left, it becomes 121-. Therefore it is not a palindrome.
Example 3:
Input: x = 10
Output: false
Explanation: Reads 01 from right to left. Therefore it is not a palindrome.
Constraints:
-231 <= x <= 231 - 1
Follow up: Could you solve it without converting the integer to a string?
Solution
Comprehensive Solution: Palindrome Number
1. Problem Deconstruction
Rewrite the Problem
Technical Definition:
Given a signed 32-bit integer x, return a boolean indicating whether the decimal representation of x (in base-10, without extraneous leading zeros except for the number 0 itself) exhibits reflectional symmetry about its center when read left-to-right versus right-to-left. Formally, for with digits where and unless and , the condition is for all . For , return false due to the leading minus sign.
Beginner-Friendly Explanation:
We’re checking if a number reads the same forwards and backwards, like the word “racecar”. For example, 121 is a palindrome because it’s 121 whether you read left-to-right or right-to-left. However, -121 is not because reversing gives “121-”, which is different. Also, 10 becomes “01” when reversed, so it’s not a palindrome.
Mathematical Formulation:
Let with . Define the digit-extraction function where and for , with for . Then is a palindrome iff and .
Constraint Analysis
-
Range:
- This bounds the number of decimal digits to at most 10 ( has 10 digits). Thus, any algorithm where is digit count runs in effectively constant time.
- Hidden implication: Numbers ending with 0 (except 0 itself) cannot be palindromes because reversal would produce a leading zero, violating standard integer representation.
- Edge cases:
- : Single digit, trivially palindrome.
- : All are palindromes.
- Negative numbers: Immediately false due to minus sign.
- Numbers with trailing zeros: e.g., 10, 100, 500; all non-palindromic.
- Large palindromes within range: e.g., 123454321, 999999999.
- Maximum integer 2147483647: Not a palindrome; minimum -2147483648: Not a palindrome.
-
Follow-up constraint: “Solve without converting integer to string”
- Eliminates straightforward string-reversal approaches, forcing mathematical digit manipulation or other integer-only techniques.
- Implies space optimization: should aim for auxiliary space.
2. Intuition Scaffolding
Analogies
-
Real-World Metaphor (Mirror Writing):
Imagine writing the number on a transparent sheet. Holding it up to a mirror, a palindrome number appears identical in the mirror as it does directly. Negative numbers show a minus sign on one side but not the other, breaking the symmetry. -
Gaming Analogy (Symmetric Puzzle):
In a tile-matching game where digits are on tiles arranged in a row, you win if the sequence is symmetric about the center. You compare the leftmost tile with the rightmost, moving inward. If all pairs match, you’ve found a palindrome. -
Mathematical Analogy (Polynomial Symmetry):
A number is a polynomial evaluated at : . A palindrome corresponds to a symmetric coefficient vector, i.e., where .
Common Pitfalls (5+ Intuitive-But-Wrong Approaches)
- Global Min/Max Reversal: Attempting to reverse the entire number without considering overflow. For , reversed is , causing 32-bit integer overflow.
- String Conversion with Negation: Converting to string, removing the minus sign, reversing, and comparing yields “121” == “121” → true, incorrectly returning true.
- Leading Zero Ignorance: For , reversing digits yields , then comparing → false, but if one mistakenly treats reversed “01” as numeric 10, error occurs.
- Half-Reversal Termination Condition: Stopping reversal when instead of can miss odd-digit palindromes (e.g., 12321).
- Log10 for Digit Count without Zero Handling: Using fails for because is undefined.
- Array Reversal Without Negative Check: Storing digits in array and comparing without first checking would incorrectly treat as palindrome.
3. Approach Encyclopedia
Approach 1: Brute Force (Compare All Digit Pairs)
Idea: For each digit position , compare with its symmetric counterpart by extracting both digits via division and modulus.
Pseudocode:
function isPalindrome(x):
if x < 0: return false
k = digit_count(x) // Handle x=0 separately
for i from 0 to floor((k-1)/2):
left_digit = (x // 10^(k-1-i)) % 10
right_digit = (x // 10^i) % 10
if left_digit != right_digit:
return false
return true
Complexity Proof:
- Extracting a digit via requires time if computing power, but we can precompute powers. Let be digit count. Precomputing powers costs . Loop runs times, each extraction if powers are cached, so total time.
- Space: for storing powers of 10, or if computed on-the-fly with repeated multiplication.
Visualization:
x = 12321, k=5
i=0: left = (12321//10000)%10 = 1, right = (12321//1)%10 = 1 ✓
i=1: left = (12321//1000)%10 = 2, right = (12321//10)%10 = 2 ✓
i=2: middle digit, skip
Return true
Approach 2: Full Mathematical Reversal
Idea: Reverse the entire number mathematically and compare with original.
Pseudocode:
function isPalindrome(x):
if x < 0: return false
original = x
reversed = 0
while x > 0:
digit = x % 10
reversed = reversed * 10 + digit
x = x // 10
return original == reversed
Complexity Proof:
- Time: where is digit count. Each iteration extracts one digit (constant time), and loop runs times.
- Space: , only a few integer variables.
Visualization:
original = 121
x=121, reversed=0
Iter1: digit=1, reversed=1, x=12
Iter2: digit=2, reversed=12, x=1
Iter3: digit=1, reversed=121, x=0
121 == 121 → true
Approach 3: Half Reversal (Optimal)
Idea: Reverse only the second half of digits and compare with the first half. Stop when reversed half ≥ remaining half.
Pseudocode:
function isPalindrome(x):
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 = x // 10
return x == reversed_half or x == reversed_half // 10
Complexity Proof:
- Time: because we only process half the digits. Each iteration does constant work (mod, division, multiplication, addition).
- Space: , only two integer variables.
Visualization:
x = 1221, reversed_half = 0
Iter1: x=1221, reversed_half=0+1=1, x=122
Iter2: x=122, reversed_half=10+2=12, x=12
Now x=12 ≤ reversed_half=12 → stop
Check: x == reversed_half? 12 == 12 → true
x = 12321, reversed_half = 0
Iter1: x=12321, reversed_half=1, x=1232
Iter2: x=1232, reversed_half=12, x=123
Iter3: x=123, reversed_half=123, x=12
Stop: x=12 ≤ reversed_half=123
Check: x == reversed_half? 12 == 123? no
Check: x == reversed_half//10? 12 == 12 → true
4. Code Deep Dive
Optimal Solution (Half Reversal) with Line-by-Line Annotations
def isPalindrome(x: int) -> bool:
# Line 1-2: Immediate rejection of invalid cases
# Negative numbers cannot be palindromes due to minus sign
# Numbers ending with 0 (except 0) cannot be palindromes because
# reversal would have leading zero, changing the value
if x < 0 or (x % 10 == 0 and x != 0):
return False
# Line 3: Initialize reversed half accumulator
# This will store the second half of digits in reversed order
reversed_half = 0
# Line 4-6: Reverse second half until we reach or pass the midpoint
# Condition x > reversed_half ensures we stop at or before the center
# For odd-digit numbers, reversed_half ends up with one extra digit
while x > reversed_half:
# Extract last digit of current x and append to reversed_half
reversed_half = reversed_half * 10 + x % 10
# Remove last digit from x (floor division by 10)
x //= 10
# Line 7: Final palindrome check
# Case 1: Even digit count → x exactly equals reversed_half
# Case 2: Odd digit count → x equals reversed_half without middle digit
return x == reversed_half or x == reversed_half // 10
Edge Case Handling
-
Example 1 (x=121):
Not negative, not ending with 0. Loop:
Iter1: reversed_half=1, x=12
Iter2: reversed_half=12, x=1
Exit (x=1 ≤ 12). Return 1 == 12//10 (1 == 1) → true ✓ -
Example 2 (x=-121):
First condition triggers (x < 0) → return false immediately ✓ -
Example 3 (x=10):
x % 10 == 0 and x != 0 → return false immediately ✓ -
x=0:
x % 10 == 0 but x == 0, so condition false. Loop not entered (0 > 0 false). Return 0 == 0 or 0 == 0//10 → true ✓ -
x=1:
Loop: reversed_half=1, x=0. Exit. Return 0 == 1 or 0 == 1//10=0 → true ✓ -
x=123321 (even digits):
Loop:
Iter1: reversed_half=1, x=12332
Iter2: reversed_half=12, x=1233
Iter3: reversed_half=123, x=123
Exit (123 ≤ 123). Return 123 == 123 → true ✓
5. Complexity War Room
Hardware-Aware Analysis
- Digit Count Bound: for 32-bit integers, so is effectively from an asymptotic perspective.
- CPU Operations: Each iteration performs:
- One modulus (x % 10) → typically implemented as division remainder
- One multiplication (reversed_half * 10)
- One addition
- One integer division (x // 10)
All are single-cycle or few-cycle operations on modern ALUs.
- Memory Footprint: Three integer variables (x, reversed_half, temporary for operations) → 12-24 bytes depending on language, easily fitting in CPU registers (L1 cache latency ~0.5 ns).
- Performance at Scale: Even for hypothetical arbitrary-precision integers with digits, this algorithm would process ~500,000 iterations, still feasible ( 0.5 million operations).
Industry Comparison Table
| Approach | Time Complexity | Space Complexity | Readability (1-10) | Interview Viability |
|---|---|---|---|---|
| Brute Force (all pairs) | or | 6 | ❌ Too slow for large d | |
| String Conversion & Reverse | 10 | ✅ Easy but violates follow-up | ||
| Full Mathematical Reversal | 9 | ✅ Good, but overflow risk | ||
| Half Reversal (Optimal) | 8 | ✅ Best: no overflow, minimal operations | ||
| Digit Array + Two Pointers | 9 | ✅ Clear but extra space |
Note: = number of decimal digits, max 10 for 32-bit integers.
6. Pro Mode Extras
Variants Section
-
Palindrome in Different Bases
- Problem: Check if is palindrome in base (e.g., binary, hexadecimal).
- Solution: Adapt half-reversal algorithm using base operations: while , do , .
-
Palindrome Linked List (LeetCode 234)
- Problem: Given singly linked list head, determine if list is palindrome.
- Solution: Find middle via fast/slow pointers, reverse second half, compare node-by-node with first half, then restore list.
-
Palindrome Permutation (LeetCode 266)
- Problem: Given string s, determine if a permutation of s could form a palindrome.
- Solution: Count character frequencies; at most one character can have odd count.
-
Longest Palindromic Substring (LeetCode 5)
- Problem: Find longest palindrome substring in given string.
- Solution: Expand around center or dynamic programming.
-
Palindrome Partitioning (LeetCode 131)
- Problem: Partition s such that every substring is palindrome.
- Solution: Backtracking with palindrome checking via DP table.
-
Super Palindromes (LeetCode 906)
- Problem: Find numbers that are palindromes and also squares of palindromes.
- Solution: Generate palindromes within range, square them, check if square is palindrome.
Interview Cheat Sheet
- First Response: “I’ll check edge cases: negatives → false, numbers ending with 0 (except 0) → false.”
- Complexity Statement: “Since the number of digits is at most 10, any algorithm is effectively constant time, but I’ll aim for optimal half-reversal to satisfy the no-string constraint.”
- Walkthrough Steps:
- Handle negative and trailing-zero cases.
- Initialize reversed_half = 0.
- While x > reversed_half: reverse last digit onto reversed_half, remove from x.
- Compare x with reversed_half (even digits) or reversed_half//10 (odd digits).
- Test Thoroughly:
- Positive palindromes: 121, 1221, 12321, 1, 0
- Negative: -121, -1
- Non-palindromes: 10, 123, 100, -101
- Mention Alternatives: “We could convert to string and compare with reverse, but that uses extra space. The mathematical reversal avoids that, and half-reversal minimizes operations.”
- Error Prevention: “Watch for overflow when reversing entire number; half-reversal avoids that. Also ensure correct handling of odd/even digit counts.”
Final Note: The half-reversal algorithm optimally balances efficiency, clarity, and adherence to constraints, making it the preferred solution for both interviews and production code where integer-only manipulation is required.