🚀 Phases 1–5 are live — Days 1–17 cover the foundations and the algorithmic patterns. See the roadmap →

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^5
  • s consists only of printable ASCII characters.

State design

  1. Flavor? Opposite-ends.
  2. Pointers? l = 0, r = n − 1.
  3. Movement? Skip non-alphanumerics on each side. Once both point at alphanumerics, compare lowercased characters. If equal, advance both. If not, return false.
  4. Stop? When l >= r. If we never returned false, return true.

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 by l at most once and by r at most once.
  • Space: O(1).

Same skin

  • Valid Palindrome II — allowed to delete at most one character; on first mismatch, try skipping l or r and 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.