Valid palindrome
Return True if a string is a palindrome, ignoring case and non-alphanumeric characters. 'A man, a plan, a canal: Panama' → True.
A palindrome reads the same forwards and backwards: "madam", "racecar", "12321". The interesting part here is the cleanup. Real sentences have capitals, spaces, commas and colons, and all of those have to be ignored.
Test cases worth running:
'A man, a plan, a canal: Panama'→True'race a car'→False'Was it a car or a cat I saw?'→True' '→True(nothing left after cleaning, and an empty string reads the same both ways)
Ask yourself first: should digits count? Here they do, so '1a2' is not a palindrome but '1a1' is.
Starter code
def is_palindrome(s):
pass
💡 Hint 1
Filter with str.isalnum()
✅ Show solution
def is_palindrome(s):
t = [c.lower() for c in s if c.isalnum()]
return t == t[::-1]
How it works
The list comprehension keeps only letters and digits (isalnum()), lowercased. Then it compares the list with its reverse.
It's short and readable, which is what I'd write in real code. In an interview you may be asked to do it without building a new list, using two pointers:
def is_palindrome(s):
i, j = 0, len(s) - 1
while i < j:
if not s[i].isalnum():
i += 1
elif not s[j].isalnum():
j -= 1
elif s[i].lower() != s[j].lower():
return False
else:
i += 1
j -= 1
return True
One pointer starts at each end, skips anything that isn't a letter or digit, and compares as they move inward.
Complexity: both versions are O(n) time. The first uses O(n) extra memory; the two-pointer version uses O(1).
A small thing that trips people up: isalnum() returns True for letters in other scripts too, like Hindi. For this problem that's fine, but it's worth knowing.
Tip: run your code in a local Python environment, Jupyter or Google Colab.