Wildcard Matching

HardString DP · Greedy Backtracking🧩 String DPLeetCode #44 ↗Updated

Problem

Decide whether pattern p matches the whole text s. In the pattern, ? stands for exactly one arbitrary character and * stands for any run of characters, including an empty one; every other character must match itself.
Inputs = "aa", p = "a"Outputfalse
Inputs = "aa", p = "*"Outputtrue
Inputs = "adceb", p = "*a*b"Outputtrue

0 ≤ s.length, p.length ≤ 2000  ·  s: lowercase letters  ·  p: lowercase letters, ? or *

Try it yourself

Java
class Solution {
    public boolean isMatch(String s, String p) {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
A * has only two moves: match nothing (skip it) or swallow one more char and stay. That gives a clean 2-D DP — and because only the latest star ever needs to be revisited, a greedy two-pointer scan with one backtrack point solves it in O(1) space.
PatternString DP

Instinct Two strings compared char by char (match, edit, interleave) means dp[i][j] over prefixes; one string's palindromes or splits means dp[l][r] or dp[i].

Memory hack Match? Go diagonal. Mismatch? Ask the neighbours. Up drops a char from s, left drops one from t, diagonal uses both.

Open the String DP guide →

Approaches

Brute ForceRecursion on (text index, pattern index)

Time O(2m+n)Space O(m+n)

match(i, j): if the pattern is used up, the text must be too. A * either skips itself (j+1) or eats s[i] and stays (i+1). Otherwise the current chars must agree (or be ?) and both indices advance.

Java
public boolean isMatch(String s, String p) {
    return match(s, p, 0, 0);
}

private boolean match(String s, String p, int i, int j) {
    if (j == p.length()) return i == s.length();
    char c = p.charAt(j);
    if (c == '*') {
        // star matches empty, or absorbs s[i] and stays on the star
        return match(s, p, i, j + 1) || (i < s.length() && match(s, p, i + 1, j));
    }
    return i < s.length() && (c == '?' || c == s.charAt(i)) && match(s, p, i + 1, j + 1);
}

Directly encodes the rules, but patterns with many stars branch exponentially.

At a glance

LevelApproachTimeSpace
Brute ForceRecursion on (text index, pattern index)O(2m+n)O(m+n)
BetterBottom-Up 2-D DP TableO(m·n)O(m·n)
OptimalGreedy Two Pointers with Star BacktrackO(m·n) worstO(1)
Common pitfalls
  • Forgetting trailing stars: s="ab", p="ab**" must still return true.
  • Initialising dp[0][j] as true for any pattern — only all-star prefixes match empty text.
  • Confusing this with regex * (Regular Expression Matching), where * repeats the previous char.
Interview tips
  • State the two choices for a star (empty vs. absorb one) before writing any code.
  • Present the DP first for correctness, then the greedy as an O(1)-space refinement.
  • Justify the greedy: only the most recent star needs backtracking.
Pattern
Pattern-vs-text DP → when wildcards create “skip or consume” choices on two strings.
My notes saved in this browser