Palindrome number tester
You're in a Bloomberg phone screen when the interviewer asks, "Can you tell me if a number reads the same forwards and backwards, without converting it to a string?" It sounds simple at first, but the constant space constraint changes everything. This problem, also known as Palindrome Number on other platforms, is a favorite warm-up question that tests your comfort with basic arithmetic operations and your ability to think beyond the obvious string-based approach.
TL;DR
Reverse the integer digit by digit using % 10 to extract the last digit and / 10 to strip it off. Build a new number from those extracted digits. If the reversed number matches the original, it is a palindrome. This runs in O(n) time where n is the number of digits, and uses O(1) space since we only need a few integer variables.
Why This Problem Matters
Palindrome number testing is deceptively simple. Most developers immediately reach for String.valueOf(n) and check if it equals its reverse. That works, but it misses the point. The real value of this problem is forcing you to manipulate numbers at the digit level using modular arithmetic. This skill transfers directly to problems involving digit sums, number reversal with overflow detection, and base conversion. It also shows interviewers that you can reason about space complexity beyond "just use a string."
The Core Insight: Modulo and Division
Before jumping into the full solution, let's build the intuition behind digit extraction. Two operations form the backbone of this approach:
number % 10gives you the last digit of any integernumber / 10(integer division) removes the last digit
Together, these let you peel digits off the right side of a number one at a time. Here is what that looks like for the number 1331:
Loading visualization...
Each step extracts one digit and shifts the remaining number to the right. The digits come out in reverse order: 1, 3, 3, 1. If we accumulate them into a new number by multiplying by 10 and adding each digit, we reconstruct the number in reverse.
Understanding the Problem
Given: A non-negative integer Task: Determine if it reads the same forwards and backwards Constraint: Use O(1) space (no string conversion, no arrays)
isPalindrome(1221) -> true
isPalindrome(121) -> true
isPalindrome(12) -> false
isPalindrome(0) -> true
Edge Cases to Consider
- Zero: Should return true (0 reversed is 0)
- Single digit: Any single digit number (0-9) is a palindrome
- Even-length palindrome: Like 1221 or 1331
- Odd-length palindrome: Like 121 or 12321
- Non-palindrome: Like 12 or 123
Solution Approach
The strategy is straightforward:
- Save the original input
- Peel off digits from the right using
% 10 - Build a reversed copy by accumulating digits with
reversed * 10 + digit - Strip the processed digit from the dividend using
/ 10 - When no digits remain, compare reversed to original
Let's trace through 1331 to see exactly how the variables evolve:
Loading visualization...
At the end, reversed is 1331 and the original input was 1331, so they match. This is a palindrome.
Now compare with a non-palindrome, 12:
Loading visualization...
Here reversed ends up as 21, which does not equal the original 12. Not a palindrome.
Implementation
Prefer a different language? Jump to solutions in other languages.
public class Solution {
public Boolean isPalindrome(int input) {
int reversed = 0, dividend = input, remainder;
while (dividend > 0) {
remainder = dividend % 10;
reversed = (reversed * 10) + remainder;
dividend = dividend / 10;
}
return reversed == input;
}
}
Let's walk through each piece:
reversed = 0: Accumulates the reversed number starting from zero.dividend = input: A working copy we consume digit by digit. We keepinputintact for the final comparison.remainder = dividend % 10: Extracts the rightmost digit.reversed = (reversed * 10) + remainder: Shifts existing reversed digits left by one position and tacks on the new digit.dividend = dividend / 10: Drops the rightmost digit we just processed.return reversed == input: The punchline. If the reversed reconstruction matches the original, it is a palindrome.
The loop runs once per digit, performing a fixed number of arithmetic operations each time. No allocations, no auxiliary data structures.
Complexity Analysis
Time Complexity: O(n)
The while loop iterates once for each digit in the input number. Each iteration performs three constant-time arithmetic operations (modulo, multiply-add, divide). With n digits total, the algorithm runs in O(n) time.
You might also see this written as O(log v) where v is the numeric value, since a number v has roughly log10(v) digits. Both are correct, but saying O(n) with n = number of digits is the more common convention in interviews.
Space Complexity: O(1)
We use exactly three integer variables (reversed, dividend, remainder) regardless of how large the input is. No strings, no arrays, no recursion. This is truly constant space.
Common Pitfalls
-
Modifying the input directly: If you use
inputas your loop variable and divide it down to zero, you have nothing to compare against at the end. Always work on a copy (dividend). -
Using string conversion: Converting to a string and comparing with its reverse is O(n) space. It works, but it sidesteps the entire point of the problem. An interviewer who specifies constant space will not accept this.
-
Forgetting the zero case: The loop condition
dividend > 0means the loop body never executes when input is 0. Sincereversedstarts at 0 and0 == 0, this correctly returns true. But it is worth mentioning explicitly in an interview. -
Integer overflow on reversal: For this problem, inputs are bounded by Integer.MAX_VALUE. A true palindrome reversed equals itself, so it cannot overflow. Non-palindromes that overflow during reversal just produce an incorrect reversed value, which safely returns false. In a more general version of this problem, you would need to handle overflow explicitly.
Interview Tips
When this comes up in an interview:
-
Start by clarifying constraints: "Can the input be negative? Are we limited to 32-bit integers? Is string conversion allowed?" For this problem, the answer is non-negative integers with constant space.
-
Mention the string approach first: Say something like, "The straightforward approach converts to a string and checks if it equals its reverse, but that uses O(n) space. Let me show you the constant-space approach using modular arithmetic." This demonstrates you know multiple solutions and can reason about tradeoffs.
-
Trace through a small example: Walk through a 3 or 4 digit palindrome (like 121 or 1331) showing how
reversedbuilds up. Then quickly show a non-palindrome case. This catches off-by-one issues before you code. -
Watch for follow-ups: Common follow-ups include "Can you do it by reversing only half the digits?" (yes, compare
reversedtoinputwhenreversed >= dividend) and "What about negative numbers?" (typically not considered palindromes).
Key Takeaways
- Reverse an integer digit by digit with
% 10(extract last digit) and/ 10(remove last digit), accumulating into a reversed number viareversed * 10 + remainder. - Always work on a copy of the input so the original value is preserved for the final comparison.
- The algorithm processes each digit exactly once for O(n) time and uses only three integer variables for O(1) space, satisfying the constant space constraint.
- Zero and single-digit inputs are handled automatically by the loop condition without special cases.
- Mention the string-based O(n) space alternative in interviews, then explain why the mathematical approach is preferred under the constant space constraint.
Practice Makes Perfect
Once you are comfortable with this digit-manipulation technique, try these related problems to build on the same skills:
- Reverse an integer (same digit-peeling technique, but with overflow handling)
- Happy numbers (repeated digit extraction and squaring)
- Palindrome tester for strings (two-pointer approach on characters)
This problem and hundreds of others are available on Firecode, where over 50,000 users have sharpened their interview skills and landed roles at top tech companies. Whether you are brushing up on fundamentals or grinding through advanced topics, consistent practice on problems like this one is what separates prepared candidates from everyone else.
Solutions in Other Languages
JavaScript
class Solution {
isPalindrome(input) {
let reversed = 0, dividend = input, remainder;
while (dividend > 0) {
remainder = dividend % 10;
reversed = (reversed * 10) + remainder;
dividend = Math.floor(dividend / 10);
}
return reversed === input;
}
}
Note the use of Math.floor for integer division, since JavaScript's / operator produces floating-point results.
TypeScript
class Solution {
isPalindrome(input: number): boolean {
let reversed = 0, dividend = input, remainder: number;
while (dividend > 0) {
remainder = dividend % 10;
reversed = (reversed * 10) + remainder;
dividend = Math.floor(dividend / 10);
}
return reversed === input;
}
}
Python
class Solution:
def is_palindrome(self, input_int: int) -> bool:
reversed_out, dividend, remainder = 0, input_int, 0
while dividend > 0:
remainder = dividend % 10
reversed_out = (reversed_out * 10) + remainder
dividend = dividend // 10
return reversed_out == input_int
Python's // operator performs integer (floor) division, so no extra function call is needed.
C++
class Solution {
public:
bool isPalindrome(int input) {
int reversed = 0, dividend = input, remainder;
while (dividend > 0) {
remainder = dividend % 10;
reversed = (reversed * 10) + remainder;
dividend = dividend / 10;
}
return reversed == input;
}
};
Go
func (s *Solution) IsPalindrome(input int) bool {
reversed, remainder, dividend := 0, 0, input
for dividend > 0 {
remainder = dividend % 10
reversed = (reversed * 10) + remainder
dividend = dividend / 10
}
return reversed == input
}
Scala
class Solution {
def isPalindrome(input: Int): Boolean = {
var reversed = 0
var remainder = 0
var dividend = input
while (dividend > 0) {
remainder = dividend % 10
reversed = (reversed * 10) + remainder
dividend = dividend / 10
}
reversed == input
}
}
Kotlin
class Solution {
fun isPalindrome(input: Int): Boolean {
var reversed = 0
var dividend = input
var remainder = 0
while (dividend > 0) {
remainder = dividend % 10
reversed = (reversed * 10) + remainder
dividend = dividend / 10
}
return reversed == input
}
}
Swift
class Solution {
func isPalindrome(_ input: Int) -> Bool {
var reversed = 0
var dividend = input
while dividend > 0 {
let remainder = dividend % 10
reversed = (reversed * 10) + remainder
dividend = dividend / 10
}
return reversed == input
}
}
Ruby
class Solution
def palindrome?(input)
reversed = 0
dividend = input
while dividend > 0
remainder = dividend % 10
reversed = (reversed * 10) + remainder
dividend = dividend / 10
end
reversed == input
end
end
Rust
impl Solution {
pub fn is_palindrome(&self, input: i32) -> bool {
let mut reversed = 0;
let mut dividend = input;
while dividend > 0 {
let remainder = dividend % 10;
reversed = (reversed * 10) + remainder;
dividend = dividend / 10;
}
reversed == input
}
}
C#
public class Solution {
public bool isPalindrome(int input) {
int reversed = 0, dividend = input, remainder;
while (dividend > 0) {
remainder = dividend % 10;
reversed = (reversed * 10) + remainder;
dividend = dividend / 10;
}
return reversed == input;
}
}
Dart
class Solution {
bool isPalindrome(int input) {
int reversed = 0;
int dividend = input;
while (dividend > 0) {
int remainder = dividend % 10;
reversed = (reversed * 10) + remainder;
dividend = dividend ~/ 10;
}
return reversed == input;
}
}
Dart uses ~/ for integer division instead of /.
PHP
class Solution {
public function isPalindrome(int $input): bool {
$reversed = 0;
$dividend = $input;
while ($dividend > 0) {
$remainder = $dividend % 10;
$reversed = ($reversed * 10) + $remainder;
$dividend = intdiv($dividend, 10);
}
return $reversed === $input;
}
}
PHP uses intdiv() for integer division.