LeetCode 第44题:通配符匹配

LeetCode 第44题:通配符匹配

题目描述

给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?''*' 的通配符匹配。

  • '?' 可以匹配任何单个字符。
  • '*' 可以匹配任意字符序列(包括空序列)。

匹配应该覆盖整个字符串 (s) ,而不是部分字符串。

难度

困难

题目链接

点击在LeetCode中查看题目

示例

示例 1:

输入:s = "aa", p = "a"
输出:false
解释:"a" 无法匹配 "aa" 整个字符串。

示例 2:

输入:s = "aa", p = ""
输出:true
解释:'
' 可以匹配任意字符串。

示例 3:

输入:s = "cb", p = "?a"
输出:false
解释:'?' 可以匹配 'c', 但第二个 'a' 无法匹配 'b'。

提示

  • 0 <= s.length, p.length <= 2000
  • s 仅由小写英文字母组成
  • p 仅由小写英文字母,'?''*' 组成

解题思路

动态规划解法

这道题可以使用动态规划来解决,我们定义 dp[i][j] 表示字符串 s 的前 i 个字符和模式 p 的前 j 个字符是否匹配。

关键点:

  • 当 p[j-1] 是字母时,需要与 s[i-1] 完全匹配
  • 当 p[j-1] 是 '?' 时,可以匹配任意单个字符
  • 当 p[j-1] 是 '*' 时,可以匹配零个或多个字符
  • 需要考虑空字符串的情况

具体步骤:

  1. 创建二维 dp 数组,初始化边界条件
  2. 遍历字符串和模式,根据不同字符更新 dp 数组
  3. 处理 '*' 的特殊情况
  4. 返回最终结果 dp[s.Length][p.Length]

图解思路

算法步骤分析表

步骤 操作 dp状态 说明
初始状态 初始化 dp[0][0]=true 空字符串匹配
第一步 处理 * dp[0][j]=dp[0][j-1] 处理开头的 *
第二步 字符匹配 dp[i][j]=dp[i-1][j-1] 字符相等或 ?
第三步 星号匹配 dp[i][j]=dp[i][j-1]∣∣dp[i-1][j] 处理 *

状态/情况分析表

情况 输入 输出 说明
完全匹配 "aa","aa" true 精确匹配
问号匹配 "aa","?a" true ? 匹配单字符
星号匹配 "aa","*" true * 匹配全部

代码实现

C# 实现

public class Solution {
    public bool IsMatch(string s, string p) {
        int m = s.Length, n = p.Length;
        bool[,] dp = new bool[m + 1, n + 1];
      
        // 初始化空字符串匹配
        dp[0, 0] = true;
      
        // 处理开头的星号
        for (int j = 1; j <= n; j++) {
            if (p[j - 1] == '*') {
                dp[0, j] = dp[0, j - 1];
            }
        }
      
        // 填充dp数组
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= n; j++) {
                if (p[j - 1] == '*') {
                    dp[i, j] = dp[i - 1, j] || dp[i, j - 1];
                } else if (p[j - 1] == '?' || s[i - 1] == p[j - 1]) {
                    dp[i, j] = dp[i - 1, j - 1];
                }
            }
        }
      
        return dp[m, n];
    }
}

执行结果

  • 执行用时:76 ms
  • 内存消耗:39.8 MB

代码亮点

  1. 🎯 使用动态规划解决复杂的匹配问题
  2. 💡 巧妙处理 '*' 的匹配逻辑
  3. 🔍 清晰的状态转移方程
  4. 🎨 代码结构简洁,易于理解

常见错误分析

  1. 🚫 没有正确处理空字符串的情况
  2. 🚫 '*' 匹配逻辑处理不当
  3. 🚫 边界条件判断错误
  4. 🚫 状态转移方程写错

解法对比

解法 时间复杂度 空间复杂度 优点 缺点
递归回溯 O(2^n) O(n) 直观易懂 效率低
动态规划 O(mn) O(mn) 效率高 空间消耗大
贪心算法 O(mn) O(1) 空间优化 实现复杂

相关题目

posted @ 2025-03-06 21:26  旧厂街小江  阅读(181)  评论(0)    收藏  举报