leetcode10:正则表达式匹配(三种解法)

1. 题目

在这里插入图片描述在这里插入图片描述

2.题目意思

写一个正则表达式出来。

3.代码

解法1:
class Solution:
    def isMatch(self, s, p):
        s_len = len(s)
        p_len = len(p)

        if p_len == 0:
            return s_len==0 # 如果长度为0,返回s是否长度为0
        
        if p_len > 1 and p[1] == '*': # 如果p的首字母后面是*
            return self.isMatch(s, p[2:]) or (s_len !=0 and (s[0]==p[0] or p[0] == '.') and self.isMatch(s[1:], p)) 
            # 1.*表示匹配0个字母,故s和p[2:]继续匹配。 2.s长度不为0,且第一项相等或者p第一项是0(可以匹配任意),并和s[1:]继续匹配(.表示匹配任意多字符或者首项相等匹配多个字母)
        else:
            return s_len != 0 and (s[0]==p[0] or p[0]=='.') and self.isMatch(s[1:], p[1:])
            # 判断长度是否为0且首项相等或者首项为.且继续匹配s[1:]和p[1:]

思路:递归~

如果p[1]*,讨论表示0个或者非0个或者前面是.
否则,讨论首项是否相等或者第一项是.

细一点,不要漏情况。这种方法时间画的较多。

解法2:
class Solution:
    def isMatch(self, s, p):
        mem  = [[None]*(len(p)+1) for _ in range(len(s)+1)]
        # mem[i][j]表示s[0:i]和p[0:j]的匹配情况
        # 遍历到最后一位还会往后遍历,所以长度+1防止超过列表索引范围
        return self.is_match(s, p ,mem)

    def is_match(self, s, p, mem):
        s_len = len(s)
        p_len = len(p)

        if p_len == 0:
            return s_len == 0 # p=0,判断s==0

        if mem[s_len][p_len] != None: # 记忆化搜索
            return mem[s_len][p_len]
        
        if p_len > 1 and p[1] == '*': # 和解法一一样,稍作修改
            mem[s_len][p_len] = self.is_match(s, p[2:], mem) or (s_len!=0 and (s[0]==p[0] or p[0]=='.') and self.is_match(s[1:], p, mem))
            return mem[s_len][p_len]
        else:
            mem[s_len][p_len] = s_len != 0 and (s[0]==p[0] or p[0]=='.') and self.is_match(s[1:], p[1:], mem)
            return mem[s_len][p_len]

思路:记忆化递归

引入一个列表来记录,减少冗余,速度比解法一快了20多倍~

解法三:
class Solution:
    def isMatch(self, s, p):
        s_len, p_len = len(s), len(p)
        mem = [[False]*(p_len+1) for _ in range(s_len+1)]
        mem[0][0] = True
        for i in range(s_len+1):
            for j in range(1, p_len+1):
                if p[j-1] == '*':
                    mem[i][j] = j>1 and mem[i][j-2] or (i>0 and (s[i-1] == p[j-2] or j>1 and p[j-2] == '.') and i>0 and mem[i-1][j])
                else:
                    mem[i][j] = i>0 and mem[i-1][j-1] and ((i>0 and s[i-1]==p[j-1]) or p[j-1]=='.')
        return mem[-1][-1]

思路:dp

对前面的代码稍微改动一下即可,状态转移方程也很好推。
if p[j-1] == '*',如果表示0个字母,则dp[i][j]=dp[i][j-2];如果同时满足s[i-1]=p[j-2]或者p[j-2]='.',说明匹配到了一个或多个,则dp[i][j]=dp[i-1][j]
else,若s[i-1]=p[j-1]或者p[j-1]='.',则也能匹配,有dp[i][j]=dp[i-1][j-1]

从递归入手,由浅入深~
冲冲冲

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值