A detailed explanation of checking whether an integer is a palindrome using digit operations without converting it to a string.
Problem Restatement
We are given an integer x.
Return true if x is a palindrome integer.
Return false otherwise.
A palindrome reads the same forward and backward. For example:
121is a palindrome because it reads the same from both directions.
But:
-121is not a palindrome, because reversing it gives:
121-The follow-up asks whether we can solve the problem without converting the integer to a string. The input range is -2^31 <= x <= 2^31 - 1.
Input and Output
| Item | Meaning |
|---|---|
| Input | An integer x |
| Output | true if x is a palindrome, otherwise false |
| Constraint | -2^31 <= x <= 2^31 - 1 |
| Follow-up | Solve without converting the integer to a string |
Example function shape:
def isPalindrome(x: int) -> bool:
...Examples
Example 1:
x = 121Output:
trueExplanation:
121reads the same forward and backward.
Example 2:
x = -121Output:
falseA negative sign appears only on the left side. So a negative number cannot read the same backward.
Example 3:
x = 10Output:
falseReading backward gives:
01which is not the same integer form as:
10First Thought: Convert to String
The simplest solution is to convert the number to a string and compare it with its reverse.
class Solution:
def isPalindrome(self, x: int) -> bool:
s = str(x)
return s == s[::-1]This works for the basic problem.
But the follow-up asks for a solution without string conversion, so we should solve it with arithmetic.
Key Insight
We can reverse only the second half of the number.
For example:
x = 1221Take digits from the right side and build a reversed half:
x = 122, reversed_half = 1
x = 12, reversed_half = 12Now compare:
x == reversed_half
12 == 12So 1221 is a palindrome.
For an odd number of digits:
x = 12321After reversing half:
x = 12, reversed_half = 123The middle digit does not matter.
So we compare:
x == reversed_half // 10
12 == 12This is why the final condition has two cases:
x == reversed_half or x == reversed_half // 10Early Rejections
Negative numbers cannot be palindromes:
x < 0Numbers ending in 0 also cannot be palindromes unless the number is exactly 0.
For example:
10would need to read backward as:
01But integers do not keep leading zeros.
So we reject:
x != 0 and x % 10 == 0Algorithm
- If
x < 0, returnFalse. - If
xends in0andx != 0, returnFalse. - Set
reversed_half = 0. - While
x > reversed_half:- take the last digit of
x - append it to
reversed_half - remove the last digit from
x
- take the last digit of
- Return whether:
x == reversed_half, for even digit count- or
x == reversed_half // 10, for odd digit count
Correctness
At each loop step, we move one digit from the end of x into reversed_half.
The operation:
reversed_half = reversed_half * 10 + x % 10appends the last digit of x to the reversed half.
The operation:
x //= 10removes that digit from x.
So after k steps:
xcontains the original number without its lastkdigitsreversed_halfcontains thosekremoved digits in reversed order
The loop stops when reversed_half has at least as many digits as x.
For even digit counts, both halves should be equal.
For odd digit counts, reversed_half has one extra middle digit, so we drop it with integer division by 10.
Therefore the algorithm returns True exactly when the original integer reads the same forward and backward.
Complexity
| Metric | Value | Why |
|---|---|---|
| Time | O(log10(x)) | We process half of the decimal digits |
| Space | O(1) | Only integer variables are stored |
For the given 32-bit range, this is bounded by a small constant.
Implementation
class Solution:
def isPalindrome(self, x: int) -> bool:
if x < 0:
return False
if x != 0 and x % 10 == 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 // 10Code Explanation
Reject negative numbers:
if x < 0:
return FalseReject numbers like 10, 100, and 1230:
if x != 0 and x % 10 == 0:
return FalseThen reverse only half of the number:
while x > reversed_half:Move the last digit from x to reversed_half:
reversed_half = reversed_half * 10 + x % 10
x //= 10Finally compare the two halves:
return x == reversed_half or x == reversed_half // 10The first comparison handles even digit counts.
The second comparison handles odd digit counts.
Testing
def run_tests():
s = Solution()
assert s.isPalindrome(121) is True
assert s.isPalindrome(-121) is False
assert s.isPalindrome(10) is False
assert s.isPalindrome(0) is True
assert s.isPalindrome(1221) is True
assert s.isPalindrome(12321) is True
assert s.isPalindrome(1231) is False
assert s.isPalindrome(1001) is True
assert s.isPalindrome(100) is False
print("all tests passed")
run_tests()| Test | Why |
|---|---|
121 | Basic odd-length palindrome |
-121 | Negative number |
10 | Ends with zero |
0 | Zero is a palindrome |
1221 | Even-length palindrome |
12321 | Odd-length palindrome |
1231 | Non-palindrome |
1001 | Internal zeros |
100 | Trailing zeros |