Wildcard Matching
HardUpdated: Aug 2, 2025
Practice on:
Problem
Given an input string (s) and a pattern (p), implement wildcard pattern matching with support for '?' and '*' where:
'?'Matches any single character.'*'Matches any sequence of characters (including the empty sequence).
The matching should cover the entire input string (not partial).
Examples
Example 1:
Input: s = "aa", p = "a"
Output: false
Explanation: "a" does not match the entire string "aa".
Example 2:
Input: s = "aa", p = "*"
Output: true
Explanation: '*' matches any sequence.
Example 3:
Input: s = "cb", p = "?a"
Output: false
Explanation: '?' matches 'c', but the second letter is 'a', which does not match 'b'.
Similar Problems
Leetcode 44 Vs Leetcode 10 OR [Regular Expression Matching](regular-expression-matching)
This problem look very similar to Leetcode 10. But actually it is slightly different.
Examples for Leetcode 10
isMatch("aa","a") ? false
isMatch("aa","aa") ? true
isMatch("aaa","aa") ? false
isMatch("aa", "a*") ? true
isMatch("aa", ".*") ? true
isMatch("ab", ".*") ? true
isMatch("aab", "c*a*b") ? true
Similar Examples for Leetcode 44 Aka Current Problem
isMatch("aa","a") ? false
isMatch("aa","aa") ? true
isMatch("aaa","aa") ? false
isMatch("aa", "*") ? true
isMatch("aa", "a*") ? true
isMatch("aa", "?*") ? true
isMatch("aab", "c*a*b") ? false
Solution
Method 1 - Recursion
We have following cases in recursion:
- Base Case:
- If we've reached the end of the pattern
p(j == p.length()), the stringsmust also be fully matched (i == s.length()).
- If we've reached the end of the pattern
- Recursive Case:
- If the current character in the pattern is
'*', it can match zero or more characters froms:isMatchHelper(s, p, i, j + 1): Considers'*'as matching zero characters.isMatchHelper(s, p, i + 1, j): Considers'*'as matching one or more characters.
- If the current character in the pattern is
'?'or matches the current character ins:- Move to the next character in both
sandp.
- Move to the next character in both
- If the current character in the pattern is
Code
Java
public class Solution {
public boolean isMatch(String s, String p) {
return isMatchHelper(s, p, 0, 0);
}
private boolean isMatchHelper(String s, String p, int i, int j) {
if (j == p.length()) {
return i == s.length();
}
if (p.charAt(j) == '*') {
// '*' matches zero characters or matches one character and moves to next in s
return isMatchHelper(s, p, i, j + 1) || (i < s.length() && isMatchHelper(s, p, i + 1, j));
} else {
// Match current character or '?'
return i < s.length() && (p.charAt(j) == s.charAt(i) || p.charAt(j) == '?') && isMatchHelper(s, p, i + 1, j + 1);
}
}
}
Complexity
-
⏰ Time complexity:
O(2 ^ (m + n)), wheremis length of s andnis length ofp- Worst-Case Scenario can be that every character in the pattern is
*. This results in two recursive calls for each character in the pattern, leading to exponential growth. - The total depth of the recursion tree can be up to the sum of the lengths of
sandpbecause each step potentially moves forward either ins,p, or both.
- Worst-Case Scenario can be that every character in the pattern is
-
🧺 Space complexity:
O(m + n), for using the recursion stack
Method 2 - Top Down DP with memoization
We can use a map to store results of subproblems, avoiding redundant computations with memoization, indexed by the string "i,j" where i is the current index in s and j is the current index in p.
Code
Java
public class Solution {
public boolean isMatch(String s, String p) {
Map<String, Boolean> memo = new HashMap<>();
return isMatchHelper(s, p, 0, 0, memo);
}
private boolean isMatchHelper(String s, String p, int i, int j, Map<String, Boolean> memo) {
String key = i + "," + j;
if (memo.containsKey(key)) {
return memo.get(key);
}
if (j == p.length()) {
return i == s.length();
}
boolean result;
if (p.charAt(j) == '*') {
result = isMatchHelper(s, p, i, j + 1, memo) || (i < s.length() && isMatchHelper(s, p, i + 1, j, memo));
} else {
result = i < s.length() && (p.charAt(j) == s.charAt(i) || p.charAt(j) == '?') && isMatchHelper(s, p, i + 1, j + 1, memo);
}
memo.put(key, result);
return result;
}
}
Complexity
- ⏰ Time complexity:
O(m*n) - 🧺 Space complexity:
O(m*n)- for using memoization map -
O(m*n), - for using recursion stack -
O(m + n)
- for using memoization map -
Method 3 - Bottom up DP
We can change the code to use bottom up DP. Here are the steps:
- Initialization:
- Create a 2D boolean array
dpwith dimensions(m + 1) x (n + 1)wheremis the length of the input stringsandnis the length of the patternp. dp[i][j]represents if the firsticharacters ofsmatch the firstjcharacters ofp.
- Create a 2D boolean array
- Base Case:
dp[0][0]istruebecause an empty string matches an empty pattern.- Handle the cases where the pattern starts with
*, which can match an empty sequence.
- DP Table Filling:
- Iterate over each character of
sandp. - For each
*in the pattern:dp[i][j]becomestrueif either:- The
*matches zero characters (i.e., the previous statedp[i][j - 1]). - The
*matches one or more characters (i.e., the previous statedp[i - 1][j]).
- The
- For each
?or exact character match:dp[i][j]is set based ondp[i - 1][j - 1].
- Iterate over each character of
- Result:
- The final result is stored in
dp[m][n], indicating whether the entire input stringsmatches the patternp.
- The final result is stored in
Code
Java
public class Solution {
public boolean isMatch(String s, String p) {
int m = s.length();
int n = p.length();
// Initialize a 2D DP array
boolean[][] dp = new boolean[m + 1][n + 1];
// An empty pattern matches an empty string
dp[0][0] = true;
// Handle patterns with '*' that can match empty sequence
for (int j = 1; j <= n; j++) {
if (p.charAt(j - 1) == '*') {
dp[0][j] = dp[0][j - 1];
}
}
// Fill the DP table
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (p.charAt(j - 1) == '*') {
// '*' can match any sequence (empty or non-empty)
dp[i][j] = dp[i][j - 1] || dp[i - 1][j];
} else if (p.charAt(j - 1) == '?' || p.charAt(j - 1) == s.charAt(i - 1)) {
// '?' matches any single character
// Characters must match for non-wildcards
dp[i][j] = dp[i - 1][j - 1];
}
}
}
// The result is in the bottom-right corner of the DP table
return dp[m][n];
}
}
Complexity
- ⏰ Time complexity:
O(m*n) - 🧺 Space complexity:
O(m*n)