17. Valid Palindrome
easyAsked at PlaidDetermine if a string is a palindrome after removing non-alphanumerics and lowercasing. Plaid asks this as a string-normalization warm-up before harder merchant-name canonicalization problems.
By Alex Chen, Founder, InterviewChamp.AI · Last verified
Source citations
Public interview reports confirming this problem appears in Plaid loops.
- Glassdoor (2025)— Plaid SWE I OA — palindrome with normalization.
- LeetCode Discuss (2026)— Plaid intro.
Problem
A phrase is a palindrome if, after converting all uppercase letters into lowercase letters and removing all non-alphanumeric characters, it reads the same forward and backward. Given a string s, return true if it is a palindrome, or false otherwise.
Constraints
1 <= s.length <= 2 * 10^5s consists only of printable ASCII characters.
Examples
Example 1
s = "A man, a plan, a canal: Panama"trueExample 2
s = "race a car"falseApproaches
1. Normalize, reverse, compare
Filter, lowercase, then check normalized === normalized.reverse().
- Time
- O(n)
- Space
- O(n)
function isPalindrome(s) {
const clean = s.toLowerCase().replace(/[^a-z0-9]/g, '');
return clean === clean.split('').reverse().join('');
}Tradeoff: Readable but allocates two extra strings.
2. Two-pointer in-place
Pointers from both ends. Skip non-alphanumerics. Compare characters lowercased.
- Time
- O(n)
- Space
- O(1)
function isPalindrome(s) {
const isAlnum = c => /[a-z0-9]/i.test(c);
let i = 0, j = s.length - 1;
while (i < j) {
while (i < j && !isAlnum(s[i])) i++;
while (i < j && !isAlnum(s[j])) j--;
if (s[i].toLowerCase() !== s[j].toLowerCase()) return false;
i++; j--;
}
return true;
}Tradeoff: No allocation. Cleaner for very long strings. The 'skip non-alnum' inner loops keep the pointers moving toward the middle.
Plaid-specific tips
Plaid grades this on whether you handle the normalization step explicitly. Bonus signal: ask whether to skip whitespace AND punctuation, or just whitespace. Their merchant-canonicalization treats 'AMZN MKT' and 'amzn-mkt' as equivalent — this primitive is the building block.
Common mistakes
- Forgetting to lowercase before comparing.
- Using a regex inside the loop without anchoring — can match unexpected characters.
- Off-by-one when both pointers land on the same non-alnum and never advance.
Follow-up questions
An interviewer at Plaid may pivot to one of these next:
- Allow up to k character deletions and still be a palindrome.
- Find the longest palindromic substring (LC 5).
- Normalize merchant names for fuzzy matching — same pattern, broader equivalence rules.
Solve it now
Free. No sign-up. Python and JavaScript run instantly in your browser.
FAQ
What if the string is empty after filtering?
Treat it as a palindrome (vacuously true). The two-pointer loop never executes, so the early-return is implicit.
Why two pointers over reverse?
No allocation, and you bail on the first mismatch — important for huge strings where most non-palindromes fail in the first few chars.
Practice these live with InterviewChamp.AI
Drill Valid Palindrome and other Plaid interview questions under real-loop conditions with instant feedback on your reasoning, complexity claims, and code.
Practice these live with InterviewChamp.AI →