◀ THE GRIND — TWO POINTERS

Valid Palindrome II

The drill: A near-palindrome test: the string earns its pass if deleting at most one character — or none at all — leaves something that reads identically both ways. The whole game is what you do at the first mismatch.

THE BRIEFING — THE FULL DRILL, IN MY OWN WORDS

A string arrives with one allowance: you may delete a single character from it — or none at all — and the question is whether some choice of that single deletion leaves a string that reads identically forwards and backwards.

The deletion, if used, can come from anywhere in the string, not just the ends. Using zero deletions is always a legal choice when the string is already a palindrome.

Only one character total may ever be removed; needing two or more disqualifies the string. The answer is a simple yes or no, not the resulting string itself.

EX 01
s = "repaper"
true
ALREADY A PALINDROME — ZERO DELETIONS
EX 02
s = "radkar"
true
MIDDLE MISMATCH, EITHER SIDE WORKS
EX 03
s = "acbba"
true
ONLY THE LEFT SKIP SAVES IT
THE HINTS — TAKE ONLY WHAT YOU NEED
HINT 1 THE NUDGE

Deleting every candidate character and re-checking works, but it re-reads the whole string n times — and almost every one of those deletions was never in doubt.

HINT 2 THE STRUCTURE

Walk inward from both ends. While the two characters agree there is nothing worth deleting — the only real decision point is the first disagreement.

HINT 3 ONE STEP FROM THE ANSWER

At the first mismatch you get one skip: drop the left character or drop the right one, and whichever remainder you keep must be a plain palindrome. Check both; either passing is a yes.

COACH'S BOARD — THE PATTERN, STEP BY STEP
ONE SKIP AT THE MISMATCHPATTERN · TWO POINTERS + ONE ALLOWED SKIPs = "abbca"
a
b
b
c
a
STEP 1

Walk inward while characters agree; the only real decision is at the first disagreement.

STEP 1 / 6 · ← → WORK TOO
THE SPLITS — TWO PACES, TWO LANGUAGES
grind/valid-palindrome-ii.pyRACE PACE
LANG ▸
PACE ▸
class Solution:
    def validPalindrome(self, s: str) -> bool:
        def is_pal(l, r):
            while l < r:
                if s[l] != s[r]:
                    return False
                l += 1
                r -= 1
            return True

        l, r = 0, len(s) - 1
        while l < r:
            if s[l] != s[r]:
                # one skip allowed: drop the left char or the right char
                return is_pal(l + 1, r) or is_pal(l, r - 1)
            l += 1
            r -= 1
        return True
TIME O(N)SPACE O(1)PYTHON · RACE PACE · 18 LN

✓ CHIP-TIMED — ALL 4 SOLUTIONS RAN GREEN AGAINST SELF-AUTHORED CASES IN CI · JDK 21 · CPYTHON 3.12 · NOTHING PUBLISHES RED