AlgoMaster Logo

Valid Palindrome

easyFrequency4 min readUpdated June 23, 2026

Understanding the Problem

This is more than a plain "is this string a palindrome?" check. The problem adds two preprocessing rules: ignore case and ignore non-alphanumeric characters. The string "A man, a plan, a canal: Panama" has spaces, commas, and a colon, but after removing those characters and lowercasing the rest, it becomes "amanaplanacanalpanama", which reads the same forwards and backwards.

The two approaches below differ on one decision: whether to build the cleaned-up string explicitly, or skip the ignored characters while comparing.

Key Constraints:

  • 1 <= s.length <= 2 * 10^5 → With up to 200,000 characters, the solution needs to run in O(n) time. Both approaches do; they differ in space usage.
  • s consists only of printable ASCII characters → The input can contain letters, digits, spaces, punctuation, and symbols, but no Unicode characters. This means a single byte per character and a fixed test for "alphanumeric".

Approach 1: Filter and Reverse

Intuition

Do exactly what the problem describes: remove everything that isn't a letter or digit, convert the rest to lowercase, and check whether the result is a palindrome.

To check whether a string is a palindrome, compare it against its reverse. If the cleaned string equals its reverse, it is a palindrome.

Algorithm

  1. Iterate through every character in the input string.
  2. Keep only alphanumeric characters, converting each to lowercase.
  3. Build a new "cleaned" string from these characters.
  4. Reverse the cleaned string.
  5. Compare the cleaned string with its reverse. If they match, return true.

Example Walkthrough

1Input: s = "race a car". Build cleaned string by keeping only alphanumeric chars (lowercased)
0
r
1
a
2
c
3
e
4
5
a
6
7
c
8
a
9
r
1/4

Code

This approach allocates a cleaned string and a reversed copy, both up to n characters. The next approach removes those allocations by comparing characters directly on the original string from both ends.

Approach 2: Two Pointers (Optimal)

Intuition

Work directly on the original string instead of building a cleaned copy. Place one pointer at the start and one at the end. Move them toward each other, skipping any character that isn't alphanumeric. When both pointers rest on alphanumeric characters, compare them case-insensitively. If they ever differ, the string is not a palindrome. If the pointers cross without a mismatch, it is.

This does the filtering and comparison in a single pass, with no extra string allocated.

Algorithm

  1. Set left to 0 and right to the last index of the string.
  2. While left < right:
    • Move left forward while it points to a non-alphanumeric character.
    • Move right backward while it points to a non-alphanumeric character.
    • If left >= right, break (all valid characters have been compared).
    • Compare the lowercase versions of s[left] and s[right].
    • If they don't match, return false.
    • Move left forward and right backward.
  3. Return true.

Example Walkthrough

1Initialize: left=0, right=29
0
left
A
1
2
m
3
a
4
n
5
,
6
7
a
8
9
p
10
l
11
a
12
n
13
,
14
15
a
16
17
c
18
a
19
n
20
a
21
l
22
:
23
24
P
25
a
26
n
27
a
28
m
29
right
a
1/9

Code