Palindrome Number: Half-Reversal Without String Conversion
LeetCode 9. Palindrome Number asks you to determine whether an integer reads the same forward and backward. Negative numbers are never palindromes. The follow-up challenge: solve it without converting the integer to a string.
The key insight is that you do not need to reverse the entire number. You only need to reverse half of it and compare.
Problem statement
Given an integer x, return true if x is a palindrome and false otherwise.
121is a palindrome (reads the same forward and backward)-121is not a palindrome (the leading-means it reads differently backward)10is not a palindrome (01is not the same as10)
Approach 1: String conversion (simple baseline)
The most direct way to check is to convert the number to a string and compare it to its reverse.
def is_palindrome(x: int) -> bool:
s = str(x)
return s == s[::-1]
This works and passes on LeetCode. It runs in O(log n) time (the number of digits is proportional to log base 10 of n) and O(log n) space for the string. But the problem explicitly asks you to solve it without string conversion, and interviewers often want to see the math-based approach.
Approach 2: Half-reversal (no string conversion)
Instead of converting to a string, you can reverse the second half of the number's digits and compare it to the first half. The algorithm works as follows:
- Reject negative numbers and numbers ending in 0 (except 0 itself) immediately.
- Build a
reversed_halfby repeatedly extracting the last digit ofxand appending it toreversed_half. - Stop when
reversed_halfis greater than or equal tox. At that point, you have reversed half the digits. - For even-length numbers,
x == reversed_halfmeans palindrome. For odd-length numbers,x == reversed_half // 10means palindrome (the middle digit ends up inreversed_halfand can be discarded).
def is_palindrome(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
This approach avoids creating any string. It also avoids reversing the full number, which sidesteps potential integer overflow in languages with fixed-width integers (not a concern in Python, but important in C++ or Java).
Visual walkthrough: x = 1221
Let's trace through the half-reversal approach step by step.
Step 1: Initial state
x = 1221, reversed_half = 0. Since x > reversed_half, keep going.
Step 2: Extract last digit of x
Last digit of 1221 is 1. reversed_half = 0 * 10 + 1 = 1. x = 1221 // 10 = 122.
Step 3: Extract last digit of x again
Last digit of 122 is 2. reversed_half = 1 * 10 + 2 = 12. x = 122 // 10 = 12.
Step 4: x is no longer greater than reversed_half
x (12) equals reversed_half (12). Since x == reversed_half, 1221 is a palindrome.
After two iterations, x and reversed_half are both 12. Since x == reversed_half, the number is a palindrome. For an odd-length number like 12321, you would end up with x = 12 and reversed_half = 123, and the check x == reversed_half // 10 handles discarding the middle digit.
Why stop at half?
Reversing only half the number is more than an optimization. In languages like Java or C++, reversing the full number can overflow if the input is near the maximum integer value. By stopping at the midpoint, the reversed portion never exceeds the original, so overflow is impossible. In Python, integers have arbitrary precision, so overflow is not a practical concern. But the half-reversal approach is still worth knowing because interviewers expect it and it transfers directly to other languages.
The "reverse half and compare" pattern also appears in Palindrome Linked List (LeetCode 234), where you reverse the second half of the list and compare it node by node. The structural idea is the same even though the data structure is different.
Complexity analysis
| Metric | Value |
|---|---|
| Time | O(log n), where n is the input number. You process half the digits, and the number of digits is log base 10 of n. |
| Space | O(1). Only a few integer variables are used, regardless of input size. |
The string approach uses O(log n) space for the string allocation. The half-reversal approach brings that down to O(1).
Building blocks
This problem decomposes into two reusable pieces that appear in many other LeetCode problems.
1. Digit extraction with modular arithmetic
Pulling the last digit off a number using x % 10 and then removing it with x //= 10. This is the same micro-pattern used in Happy Number, Reverse Integer, and Add Digits.
while x > 0:
digit = x % 10
x //= 10
2. Half-reversal pattern
Building a reversed number from extracted digits and stopping when the reversed portion catches up to the remaining portion. This avoids full reversal, prevents overflow, and naturally handles both even-length and odd-length inputs with a single extra check (reversed_half // 10).
reversed_half = 0
while x > reversed_half:
reversed_half = reversed_half * 10 + x % 10
x //= 10
On CodeBricks, you drill each building block separately so that when they appear together in a problem like this, you recognize both pieces instantly.
Edge cases
- Negative numbers: Always return
false. The minus sign means the number cannot read the same in both directions. - Single-digit numbers (0 through 9): Always palindromes. The while loop condition
x > reversed_halfis immediately false, and the checkx == reversed_halfpasses since both are equal to the original number. - Trailing zeros: A number like 10 or 120 ends in zero but does not start with zero. You catch these early with
x % 10 == 0 and x != 0. Without this guard, the algorithm would incorrectly matchx = 0withreversed_half = 01(which is just 1). - Zero itself: Handled by the
x != 0exception in the trailing-zero check. Zero is a palindrome.
From understanding to recall
You can read through this solution in a few minutes and understand every line. But understanding is not the same as being able to reproduce it under interview pressure two weeks from now.
The gap between understanding and recall is where spaced repetition comes in. CodeBricks breaks Palindrome Number into its building blocks (digit extraction with mod/div, half-reversal with a stopping condition) and drills them at increasing intervals. You type each piece from scratch, building real muscle memory. After a few review cycles, the half-reversal pattern becomes automatic rather than something you have to rederive.
Related posts
- Valid Palindrome - Two-pointer palindrome check on strings, the string counterpart to this number-based problem
- Reverse Linked List - Reversing a linked list in place, another problem where working with half the structure (as in Palindrome Linked List) uses a similar idea