Valid Palindrome

25 min · isPalindrome()

A string is a palindrome when it reads the same forwards and backwards — but here we judge only the letters and digits, and we don't care about case.

Given a string s, return true if it's a palindrome under those rules, and false otherwise.

Concretely, before comparing you should treat the string as if you had:

  1. removed every character that isn't a letter or a digit, and
  2. lowercased everything that remains.

A string that ends up empty after step 1 counts as a palindrome.

Constraints

  • 1 <= s.length <= 200_000
  • s consists of printable ASCII characters (letters, digits, punctuation, spaces).

Hints

The direct route

Build the cleaned string, then compare it to its reverse. Two passes, some extra memory — perfectly valid, and worth writing first.

Meet in the middle

Put one finger on each end. If both point at alphanumeric characters, compare them (lowercased) and step both inward. If either points at junk, step just that one. You never build a second string at all.

Careful with the skips

When you skip non-alphanumerics inside the loop, make sure the two pointers can't run past each other — left < right needs re-checking inside the skip loops too.

Follow-up

Your language probably has a one-liner for this. The converging-pointers version is still worth owning: it's the same movement pattern you'll use on Two Sum II, 3Sum, and Container With Most Water — where no one-liner will save you.

Visible cases

Examples

Example 1

ready
Input
s = "A man, a plan, a canal: Panama"
Expected
true
Why
letters/digits only, case-insensitive

Example 2

ready
Input
s = "race a car"
Expected
false
Why
cleaned: 'raceacar' — reads differently backwards

Example 3

ready
Input
s = " "
Expected
true
Why
nothing left after cleaning still counts

Interview signal

Asked at

MetaAmazonMicrosoft
Loading editor

Console

ready to run

Ready to run.

3 cases are queued.

Run: visible + custom · Submit: full suite