Offer 驾到,掘友接招!我正在参与 2022 春招打卡活动,点击查看活动详情。
一、题目描述:
- 正则表达式匹配-难度困难
给你一个字符串 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)
};
四、总结:
这道题是我遇到的第一道特别难,做不出来的题目,当时跳了过去,今天又重新翻出来进行了二次解题。
这道题的思路和解题方法都很重要,错一项都解不出来。
加油吧!