Wildcard Matching - Complete Solution Guide
Wildcard Matching is LeetCode problem 44, a Hard level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
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). 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: Inpu
Detailed Explanation
The problem asks us to implement wildcard pattern matching with two special characters: '?' and '*'. The '?' character matches any single character, while the '*' character matches any sequence of characters (including an empty sequence). The goal is to determine if the given pattern 'p' matches the entire input string 's'. It's crucial that the entire string 's' must be matched, not just a part of it.
Solution Approach
The provided solutions use dynamic programming to solve the wildcard matching problem. A 1D DP array is used to store the matching results. The pattern is preprocessed to remove consecutive '*' characters. The DP array 'dp[j]' represents whether the substring 's[0...i-1]' matches 'p[0...j-1]'. The code iterates through the input string 's' and the pattern 'p', updating the DP array based on the current characters in 's' and 'p'.
Step-by-Step Algorithm
- Step 1: Preprocess the pattern 'p' to remove consecutive '*' characters. This optimization avoids redundant computations.
- Step 2: Initialize a 1D DP array 'dp' of size 'n+1' (where 'n' is the length of the preprocessed pattern). dp[0] is set to true, meaning an empty pattern matches an empty string.
- Step 3: Handle the case where the pattern starts with '*'. For all j from 1 to n, if p[j-1] == '*', dp[j] = dp[j-1]. This accounts for '*' matching an empty string at the beginning.
- Step 4: Iterate through the input string 's' (from i=1 to m) and the pattern 'p' (from j=1 to n).
- Step 5: Inside the inner loop, update 'dp[j]' based on the characters s[i-1] and p[j-1].
- Step 6: If p[j-1] is '?' or matches s[i-1], then dp[j] = dp[j-1] (meaning the current characters match, so the match depends on the previous substring match).
- Step 7: If p[j-1] is '*', then dp[j] = dp[j] || dp[j-1] (meaning '*' can either match the current character s[i-1] or match an empty string).
- Step 8: If p[j-1] is neither '?', '*', nor s[i-1], then dp[j] = false (no match).
- Step 9: After the iterations, dp[n] will contain the result: whether the entire string 's' matches the entire pattern 'p'.
Key Insights
- Insight 1: Dynamic Programming is a suitable approach because the problem exhibits overlapping subproblems (whether a substring of 's' matches a substring of 'p').
- Insight 2: The '*' character is the most important case to handle. It can either match zero characters, one character, or many characters. The DP approach allows us to consider all these possibilities.
- Insight 3: Reducing consecutive '*' characters in the pattern 'p' to a single '*' can significantly improve efficiency and simplify the logic. For example, 'a***b' is the same as 'a*b'.
Complexity Analysis
Time Complexity: O(mn)
Space Complexity: O(n)
Topics
This problem involves: String, Dynamic Programming, Greedy, Recursion.
Companies
Asked at: Adobe, Amazon, Apple, Bloomberg, Confluent, Coupang, Coursera, Google, Instacart, Meta, Microsoft, Salesforce, Snap, Twilio, Two Sigma, Uber, Walmart Labs, X, Zoho.