Valid Palindrome easy
Description
A phrase is a palindrome if, after converting all uppercase letters into lowercase 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.
Examples
> Case 1:
s = "A man, a plan, a canal: Panama"
Output: true
Explanation: filtered = "amanaplanacanalpanama" — a palindrome.
> Case 2:
s = "race a car"
Output: false
Explanation: filtered = "raceacar" — not a palindrome.
> Case 3:
s = " "
Output: true
Explanation: filtered = "" — an empty string is trivially a palindrome.Constraints
1 <= s.length <= 2 × 10^5sconsists only of printable ASCII characters.
State design
- Flavor? Opposite-ends.
- Pointers?
l = 0,r = n − 1. - Movement? Skip non-alphanumerics on each side. Once both point at alphanumerics, compare lowercased characters. If equal, advance both. If not, return
false. - Stop? When
l >= r. If we never returnedfalse, returntrue.
Code
⚠️
Don’t skip the l < r guard inside the inner loops. If the input is all non-alphanumerics (e.g., " "), without that guard l could march past r. The guard ensures we never read s[l] or s[r] after the pointers cross.
Why not just build a filtered string and compare?
def is_palindrome_brute(s):
filtered = "".join(c.lower() for c in s if c.isalnum())
return filtered == filtered[::-1]That works! It’s O(n) time. The catch: O(n) extra space for the filtered string and its reverse. The two-pointer version is O(1) extra. For an interview, the in-place version demonstrates the pattern; for production, either is fine.
Analysis
- Time:
O(n). Each character is touched bylat most once and byrat most once. - Space:
O(1).
Same skin
- Valid Palindrome II — allowed to delete at most one character; on first mismatch, try skipping
lorrand check if the rest is a palindrome. - Palindrome Linked List — find middle, reverse second half, compare with first.
- Longest Palindromic Substring — expand from center (two pointers from each potential center).
- Reverse Vowels of a String — opposite-ends, swap only at vowels.