LeetCode 算法题库【44】——通配符匹配

通配符匹配

题目描述:

ti
mu
mu

解题思路:
  • 第一种:递归。按照顺序,依次判断是否为*,因为*能代表多个不同的字符。每次判断完p都会通过切片的方式去掉判断完的字符,然后进行递归。最后剩下最后一个字符的时候判断是否为*,如果是则直接返回True,如果不是,则要判断最后这个字符和s[0]要对应相等或者最后一个字符为
  • 因为这个方法函数调用过深,会超时,所以需要换一种方法。
class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        if not p:
            return not s
        if len(p) == 1:
            if p[0] == '*':
                return True
            else:
                return len(s) == 1 and (p[0] == s[0] or p[0] == "?")
        if p[0] != "*":
            if not s:
                return False
            else:
                return (p[0] == s[0] or p[0] == "?") and self.isMatch(s[1:], p[1:])
        else:
            while s:
                if self.isMatch(s, p[1:]):
                    return True
                s = s[1:]
            return self.isMatch(s, p[1:])shidoune
  • 第二种:动态规划。首先建立动态规划模型dp,先全部默认赋给False,并且这个dp是以s字符串作为列,以p作为行,所以dp[0][0]就是当字符串sp均为空的情况,所以改成True
  • 首先先是判断当s字符串为空时,p字符串的前i项是否能匹配,如果p的这一次对应的项是*,则看它前一项是否匹配,如果匹配,则为True,所以当前项也为True。如果不匹配,则后面也都为False。当然,这里我们不去填s非空,p为空的情况,因为这样会刚好符合默认情况,也就是全为False
  • 接下来,我们开始填写dp动态规划表。我们依次遍历两个字符串,当出现相同项,或者p字符串的对应字符为?,则说明当前对应字符已匹配,且要求各往后一位也匹配。如果当前p字符串位置字符为*,则说明有三种情况,满足其一就说明匹配:1)代表空字符串。2)代表任意一个字符,也就是当前对应的。3)代表多个任意的字符。如果遍历中没有碰到相同项,则说明当前这两个字符串不匹配,就继续保持默认False。最后我们判断dp[-1][-1]是否匹配,这个也就是dp[len(p)][len(s)],即最终两个总字符串ps是否匹配。将这个结果返回就是最终的答案。
  • 时间复杂度:O(SP)
class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        s_len = len(s)
        p_len = len(p)
        dp = [[False] * (s_len+1) for _ in range(p_len+1)]
        dp[0][0] = True
        for i in range(p_len):
            if p[i] == '*':
                dp[i+1][0] = dp[i][0]
        for j in range(p_len):
            for k in range(s_len):
                if p[j] == s[k] or p[j] == '?':
                    dp[j+1][k+1] = dp[j][k]
                elif p[j] == '*':
                    dp[j+1][k+1] = dp[j][k+1] or dp[j+1][k] or dp[j][k]
        return dp[-1][-1]

1

  • 第三种:回溯法。这个方法我也是看了好久,也是个很好的方法,运行速度很快,需要好好总结学习。大体思路和动态规划很类似,只是写法上的不同。

  • 分别定义搜索sp的双指针s_indexp_index、记录*号出现的位置的star_indexp中从头能匹配到的位置s_match

  • 首先判断s字符串不为空时,从每个字符串的第一个字符开始匹配,如果匹配了,就看是验证下一个。如果p中字符为*,则记录下来出现位置给star_index,并且记录此时的s位置给s_match。然后如果*的位置不是在末尾处,则继续判断p的下一位是否匹配,然后s的判断的起始位置为s_match的下一个位置,其中s_match一直加1就是为了找到能和star_index的下一个位置匹配的。如果一直都没有出现能匹配的,且s[s_index]p[p_index]已经不匹配了,所以返回False

  • 循环结束之后,也就是s字符串全部匹配完成,如果刚好字符串p指针到最后一个元素了,则说明p也刚好匹配完成,返回True。但是如果p字符串还有剩余字符未匹配,则就要判断剩余的字符是否为*,因为如果这种情况要使得匹配成功,p字符串后面的这些字符必须要表示为空字符,而有这个能力的字符就是*,所以只有后面的字符都为*,才能使得两个字符串匹配。最后循环完成之后,如果p_index指向字符串p末尾,说明匹配完成,返回True。否则,匹配失败,返回False

  • 时间复杂度:O(SlogP)

class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        s_len, p_len = len(s), len(p)
        s_index, p_index, star_index, s_match = 0, 0, -1, 0
        while s_index < s_len:
            if p_index < p_len and (p[p_index] == s[s_index] or p[p_index] == "?"):
                s_index += 1
                p_index += 1
            elif p_index < p_len and p[p_index] == "*":
                star_index = p_index
                p_index += 1
                s_match = s_index
            elif star_index != -1:
                p_index = star_index + 1
                s_match += 1
                s_index = s_match
            else:
                return False
        while p_index < p_len and p[p_index] == "*":
            p_index += 1
        return p_index == p_len

2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值