Hook: Interviewers like this one because it looks tiny, but it quietly tests loops, edge cases, and whether you think before you code.
Question: How do you check whether a string is a palindrome in Java?
Answer: A palindrome reads the same from left to right and right to left, like abba or racecar. The cleanest solution is to compare characters from both ends and move inward until the pointers meet. If you want to ignore spaces, punctuation, and case, normalize the string while comparing instead of building a reversed copy.
Interview-Ready Answer: I would solve it with two pointers. I start one pointer at the beginning and one at the end, compare the characters, and move inward; if any pair differs, it is not a palindrome. That gives me O(n) time and O(1) extra space. If the problem says to ignore case or punctuation, I would skip non-alphanumeric characters and compare using lowercase letters.
A palindrome is anything that reads the same backward and forward. In interviews, that can mean an exact match, like abba, or a normalized match where you ignore spaces, punctuation, and case, like RaceCar or A man, a plan, a canal: Panama.
false.true.This works because every palindrome has mirrored characters at equal distance from the center. You do not need to check the middle twice, so the loop stops when left < right becomes false.
Java strings are immutable, which means you cannot edit them in place. A simple solution like new StringBuilder(s).reverse().toString() creates an extra full copy of the text. That is fine for small inputs, but two pointers avoid that extra allocation and stay memory-friendly.
| Approach | Extra Space | Good For | Trade-off |
|---|---|---|---|
| Two pointers | O(1) | Most interviews | Slightly more logic |
| Reverse and compare | O(n) | Quick code | Extra copy of string |
| Recursion | O(n) | Teaching demos | Call stack grows |
For a string of length n, the two-pointer method does at most about n/2 comparisons, so it is still O(n) time. For a million-character input, that is still only one pass, but a reverse-based solution also allocates another full copy of the characters, which is the kind of thing that matters in memory-sensitive services.
One subtle point: charAt works on UTF-16 code units, not full Unicode code points. For normal interview problems, char-based logic is fine. If you need full Unicode correctness, especially for emoji or rare symbols, iterate over code points instead of raw char values.
false unless the problem says otherwise.char-based code is fine for most interviews, but not perfect for every script.Memory hook: Think of two mirrors walking toward each other in a hallway: if every reflection matches, the string is a palindrome.
Real-World Story: A checkout team has an internal QA tool that validates mirrored voucher codes in staging so testers can spot bad data quickly. The tool checks whether the cleaned code reads the same from both ends before it is saved.
At first, a developer compared the raw input directly, so mixed-case test values and codes with spaces or punctuation were rejected even though they were meant to be valid after normalization. The bug showed up as a spike in invalid code errors, support tickets from QA, and logs full of mismatches near the center of the string.
The fix was simple but important: normalize first, then compare with two pointers. That separation keeps the rule easy to read, easy to test, and easy to change when the business rule changes.
public class PalindromeCheck {
// Exact palindrome: compares characters as-is.
// Null returns false because there is no meaningful string to validate.
public static boolean isPalindromeExact(String s) {
if (s == null) {
return false;
}
int left = 0;
int right = s.length() - 1;
while (left < right) {
if (s.charAt(left) != s.charAt(right)) {
return false;
}
left++;
right--;
}
return true;
}
// Normalized palindrome: ignores non-alphanumeric characters and case.
// This matches the common interview variant for phrases like
// "A man, a plan, a canal: Panama".
public static boolean isPalindromeNormalized(String s) {
if (s == null) {
return false;
}
int left = 0;
int right = s.length() - 1;
while (left < right) {
char lc = s.charAt(left);
char rc = s.charAt(right);
// Skip anything that should not affect the text meaning:
// spaces, punctuation, symbols, and so on.
if (!Character.isLetterOrDigit(lc)) {
left++;
continue;
}
if (!Character.isLetterOrDigit(rc)) {
right--;
continue;
}
// Lowercase comparison makes the check case-insensitive.
if (Character.toLowerCase(lc) != Character.toLowerCase(rc)) {
return false;
}
left++;
right--;
}
return true;
}
// Integer palindrome without converting to a string.
// Reversing only half the number avoids overflow and is a common interview follow-up.
public static boolean isPalindrome(int x) {
if (x < 0) {
return false; // Negative numbers are not palindromes because of the minus sign.
}
// Numbers ending in 0 cannot be palindromes unless the number is 0 itself.
if (x % 10 == 0 && x != 0) {
return false;
}
int reversedHalf = 0;
while (x > reversedHalf) {
reversedHalf = reversedHalf * 10 + (x % 10);
x /= 10;
}
// For odd-length numbers, drop the middle digit from reversedHalf.
return x == reversedHalf || x == reversedHalf / 10;
}
private static void printResult(String label, boolean result) {
System.out.println(label + " -> " + result);
}
public static void main(String[] args) {
System.out.println("Exact string checks:");
printResult("abba", isPalindromeExact("abba"));
printResult("abca", isPalindromeExact("abca"));
printResult("null", isPalindromeExact(null));
System.out.println();
System.out.println("Normalized string checks:");
printResult("A man, a plan, a canal: Panama", isPalindromeNormalized("A man, a plan, a canal: Panama"));
printResult("race a car", isPalindromeNormalized("race a car"));
printResult("empty string", isPalindromeNormalized(""));
printResult("null", isPalindromeNormalized(null));
System.out.println();
System.out.println("Integer checks:");
printResult("121", isPalindrome(121));
printResult("-121", isPalindrome(-121));
printResult("10", isPalindrome(10));
printResult("0", isPalindrome(0));
}
}Follow-up & Tricky Questions:
O(n) time and O(1) extra space. Each character is visited at most once from each side, and no extra full-size structure is needed.false for null because there is no value to check, and true for the empty string because it is already symmetric by definition. If the product rule is different, I would state that clearly.Tricky / Gotchas:
true unless the problem says otherwise.StringBuilder.reverse() always behave perfectly for Unicode? No, it reverses UTF-16 code units, so some surrogate pairs and combining marks can be tricky. For ordinary interview strings it is fine, but full Unicode correctness needs code points.10 a palindrome as an integer? No. As a number, 10 is not the same backward because a leading zero is not preserved, so it fails the palindrome check.Common Mistakes:
null or empty input. Fix: decide the rule up front and code it explicitly.Character.isLetterOrDigit and Character.toLowerCase.== for strings. Fix: == checks object identity, not text content; use character comparison or equals when needed.Memory Hook: Two mirrors walk toward each other. If every reflection matches, the string is a palindrome.
Cheat Sheet:
false immediately.O(n) time, O(1) space.Practice Tasks: