InterviewPrepKit

Home / Coding / Two Pointers

Valid Palindrome

easy Original β†—
Solving tips
  • Recognize the symmetric predicate (reads the same both ends) as textbook converging two pointers; the clean-and-compare one-liner works but misses the O(1)-space follow-up interviewers want.
  • Move left and right inward, skipping non-alphanumeric characters in place, and compare s[left].lower() vs s[right].lower(); fail fast on any mismatch, in O(n) time and O(1) space.
  • Fuse the filter into the scan rather than pre-building a cleaned copy; that is exactly what turns O(n) extra space into O(1).
  • Pitfall: digits count as alphanumeric (the '0P' trap), lowercase both sides, and re-check left < right each iteration so skip-loops don't run the pointers off the ends on all-punctuation input.

Problem

Given a string s, decide whether it is a palindrome under a relaxed reading: first imagine converting every uppercase letter to lowercase and deleting every character that is not a letter or a digit; s is a valid palindrome if what remains reads the same forwards and backwards. Return True or False.

An empty remainder (e.g. a string of only punctuation and spaces) counts as a palindrome.

Examples

  • s = "A man, a plan, a canal: Panama" β†’ True After cleaning: "amanaplanacanalpanama", which reads the same both ways.
  • s = "race a car" β†’ False Cleaned: "raceacar" β€” reversed it is "racaecar", not equal.
  • s = " " β†’ True Cleaning removes everything; the empty string is a palindrome by definition.
  • s = "0P" β†’ False Digits count: cleaned is "0p", and "0" != "p".

Constraints

  • 1 <= s.length <= 2 * 10^5
  • s consists of printable ASCII characters.
  • Expected O(n) time; the follow-up asks for O(1) extra space (no cleaned copy).

Think about it first

Hint 1 The two-step statement (clean, then compare with the reverse) can be coded literally. What does Python give you for "keep only letters and digits" and for "reverse"?
Hint 2 To avoid building the cleaned copy, compare the string against itself: one cursor from the front, one from the back. What should a cursor do when it lands on a comma or a space?
Hint 3 Advance `left` past non-alphanumerics, retreat `right` past non-alphanumerics, then compare `s[left].lower()` with `s[right].lower()`. Any mismatch β†’ `False`; if the cursors cross without mismatching β†’ `True`.
Your workspace Not runnable by design β€” this is your interview scratchpad. Saved on this device.