【力扣刷题记 10】——《正则表达式匹配》

124 阅读2分钟

Offer 驾到,掘友接招!我正在参与 2022 春招打卡活动,点击查看活动详情

一、题目描述:

  1. 正则表达式匹配-难度困难

给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。

'.' 匹配任意单个字符

'*' 匹配零个或多个前面的那一个元素

所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。

  示例 1:

输入:s = "aa", p = "a"

输出:false

解释:"a" 无法匹配 "aa" 整个字符串。

示例 2:

输入:s = "aa", p = "a*"

输出:true

解释:因为 '*' 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 'a'。因此,字符串 "aa" 可被视为 'a' 重复了一次。

示例 3:

输入:s = "ab", p = ".*"

输出:true

解释:"." 表示可匹配零个或多个('')任意字符('.')。  

提示:

1 <= s.length <= 20

1 <= p.length <= 30

s 只包含从 a-z 的小写字母。

p 只包含从 a-z 的小写字母,以及字符 . 和 *。

保证每次出现字符 * 时,前面都匹配到有效的字符

二、题目和思路分析:

匹配的根源在于如何匹配,简单来说,如果p与s完全相等即匹配。

那么是不是可以这样?

将p所有的可能列出来,得到数组arr,判断数组是否包含s,如果arr包含s,则匹配。

看起来没错,可是当p长度过长时,这个数组肯定会超时的。

那么再来分析一下:

p的所有可能: .任意字符,*前一个字符,其它字符

最重要的是: * 代表可以匹配零个或多个前面的那一个元素,也就是说 * 和 * 前面的字符是绑定在一起的。所以它的长度不定。

那么能不能反过来考虑呢?

s是否能匹配到p

如果s[i]!=p[i],那么p[i]应该是. 或者循环p[i] == * 且 p[i-1] == s[i]

这么想好像有戏,写代码试试,写了半天还是不行,要考虑的情况太多。

那么这种循环便利的方法不可取吗?难道只能用传说中的动态规划来解决问题吗?

我不禁陷入了深思......

如果声明一个方法,返回s的第i项与p的第j项匹配情况呢?看起来和动态规划的思路类似,但是循环调用,只要捋清楚一次逻辑即可,于是经过半天的调试之后,终于通过!!!

三、代码:

代码实现如下:

/**
 * @param {string} s
 * @param {string} p
 * @return {boolean}
 */
var isMatch = function(s, p) {
    let n = s.length, m = p.length
    function revTra(i, j){   
        if (i == n && j == m){
            return true
        } 
        if (i > n || j >= m){
            return false
        }

        let isSame = p[j] == '.' || s[i] == p[j]

        if (p[j + 1] == '*'){ 
            return isSame && revTra(i + 1, j) || revTra(i, j + 2)
        }
        return isSame && revTra(i + 1, j + 1)
    }

    return revTra(0, 0)

};

四、总结:

这道题是我遇到的第一道特别难,做不出来的题目,当时跳了过去,今天又重新翻出来进行了二次解题。

这道题的思路和解题方法都很重要,错一项都解不出来。

加油吧!

image.png