const solve = (nums) => { let left = 0, right = nums.length - 1; while (left < right) { const sum = nums[left] + nums[right]; if (sum === target) return [left, right]; }}
Problem Walkthrough

Valid Palindrome: LeetCode 125 Solution Explained

Valid Palindrome (#125) is the simplest opposite-direction two-pointer problem — and the perfect place to learn character filtering and case-insensitive comparison.

6 min read|

Valid Palindrome (#125): the simplest two-pointer problem

Opposite direction pointers with character filtering — the palindrome pattern

Where Opposite-Direction Two Pointers Begin

Valid Palindrome (#125) is the first opposite-direction two-pointer problem most people encounter on their LeetCode journey. It sits right at the start of NeetCode's Two Pointers section for a reason — the logic is minimal, but the technique you learn here carries forward into dozens of harder problems.

The problem asks a straightforward question: given a string, determine whether it reads the same forwards and backwards after you strip out everything except letters and digits and ignore case. That single sentence contains two separate skills — character filtering and pointer convergence — and mastering both here makes everything from Container With Most Water (#11) to 3Sum (#15) feel more approachable.

If you are looking for a valid palindrome leetcode walkthrough that focuses on the why behind each step rather than just pasting code, you are in the right place.

Understanding the Valid Palindrome Problem

LeetCode 125 gives you a string s and asks you to return true if it is a palindrome considering only alphanumeric characters and ignoring cases. The key phrase is "considering only alphanumeric characters." Spaces, punctuation, and special symbols are invisible — you skip right past them.

Take the classic example: "A man, a plan, a canal: Panama". Strip out everything that is not a letter or digit and lowercase the rest, and you get "amanaplanacanalpanama" — which reads the same in both directions. The answer is true.

Now consider "race a car". After filtering you get "raceacar". Reading backwards gives "racaecar", which does not match. The answer is false.

The constraints are generous — s can be up to 200,000 characters — but the solution only needs a single pass through the string, so performance is not a concern as long as you avoid creating unnecessary copies.

ℹ️

Why This Problem Matters

Valid Palindrome (#125) is the first two-pointer problem in NeetCode's roadmap — it teaches opposite-direction pointers that you'll use in Container With Most Water, 3Sum, and every palindrome problem.

Two Pointer Approach for Valid Palindrome

The core idea is simple: place one pointer at the start of the string and another at the end. Move them toward each other, skipping any character that is not alphanumeric. When both pointers land on valid characters, compare their lowercase versions. If they ever disagree, return false. If the pointers cross without a mismatch, the string is a palindrome.

This runs in O(n) time because each pointer moves at most n steps total, and it uses O(1) extra space because you never allocate a new string. That space efficiency is the whole reason interviewers prefer this approach over the clean-first method.

  • Initialize left = 0, right = len(s) - 1
  • While left < right, skip non-alphanumeric characters on both sides
  • Compare s[left].lower() with s[right].lower()
  • If mismatch, return false immediately
  • If match, move left forward and right backward
  • Return true when the pointers meet or cross

Clean String vs In-Place Two Pointers

There are two common ways to solve this problem, and interviewers will notice which one you pick. The first approach cleans the string upfront: filter out non-alphanumeric characters, convert to lowercase, and then check if the result equals its reverse. This is clean, readable, and perfectly correct.

The second approach uses two pointers in-place, skipping non-alphanumeric characters as you go. No new string is allocated, no reversal is computed. You compare characters directly from the original string.

Both approaches run in O(n) time, but their space usage differs. The clean approach allocates a new string of up to n characters — that is O(n) space. The two-pointer approach uses only a couple of integer variables — O(1) space. In an interview, demonstrating the two-pointer version signals that you understand space optimization and are comfortable with pointer manipulation.

If you are asked for the "optimal" solution, go with two pointers. If you are asked to write the "cleanest" solution, the filter-and-reverse one-liner is fine. Know both, lead with two pointers.

⚠️

Space Matters

Don't create a new cleaned string — the two-pointer approach works in O(1) space by skipping non-alphanumeric in-place. Creating a new string wastes O(n) space.

Visual Walkthrough of Valid Palindrome

Let us trace through "A man, a plan, a canal: Panama" step by step. Left starts at index 0 ('A'), right starts at index 29 ('a'). Both are alphanumeric. Lowercase 'a' equals lowercase 'a' — match. Move inward.

Left moves to index 1 (space) — not alphanumeric, skip. Left moves to index 2 ('m'). Right moves to index 28 ('m'). Lowercase match. Move inward again.

This process continues, with the pointers skipping every comma, colon, and space they encounter, and matching every letter pair: a-a, n-n, a-a, p-p, l-l, and so on. The pointers eventually cross in the middle. No mismatch was found, so we return true.

Now trace "race a car". Left starts at 'r', right starts at 'r'. Match. Left moves to 'a', right moves to 'a'. Match. Left moves to 'c', right moves to 'c'. Match. Left moves to 'e', right moves to space (skip), then 'a'. Lowercase 'e' does not equal 'a' — mismatch. Return false immediately without scanning the rest of the string.

Edge Cases You Need to Handle

Interviewers love edge cases on this problem because they reveal whether you truly understand the filtering step. An empty string should return true — there is nothing to contradict palindrome status. A single character is always a palindrome.

A string containing only non-alphanumeric characters like ".,;:!?" also returns true. After filtering, you are left with an empty string, and an empty string is trivially a palindrome. Your two-pointer loop simply never executes because left starts past right.

Strings with digits mixed in are another subtle case. "0P" should return false because '0' and 'p' are both alphanumeric but not equal. Make sure your isalnum check includes digits, not just letters.

  • Empty string "" -> true (trivially a palindrome)
  • Single character "a" -> true
  • All punctuation ",.!" -> true (filtered string is empty)
  • Mixed digits and letters "0P" -> false
  • Uppercase vs lowercase "Aa" -> true (case-insensitive)
💡

Pro Tip

Use isalnum() to skip non-alphanumeric characters and lower() for case-insensitive comparison — these two built-in functions handle all the filtering so you can focus on the two-pointer logic.

What Valid Palindrome Teaches You

Valid Palindrome (#125) is small, but it packs two foundational skills into one problem. First, you learn opposite-direction two pointers — starting from both ends and converging toward the middle. This exact pointer movement reappears in Container With Most Water (#11), Trapping Rain Water (#42), Two Sum II (#167), and 3Sum (#15).

Second, you learn character filtering — deciding on the fly which characters to process and which to skip. That skill shows up in string manipulation problems, parsing tasks, and anywhere you need to ignore noise in input data.

Once you are comfortable with Valid Palindrome, the natural next step is Valid Palindrome II (#680), which asks whether you can make the string a palindrome by removing at most one character. That problem builds directly on the two-pointer skeleton you learn here, adding a single branching decision when a mismatch is found.

Use YeetCode flashcards to drill the two-pointer palindrome pattern until recognizing it becomes automatic. The goal is not to memorize this specific solution — it is to internalize the pointer movement so you can adapt it to any problem that needs opposite-direction traversal.

Ready to master algorithm patterns?

YeetCode flashcards help you build pattern recognition through active recall and spaced repetition.

Start practicing now