LeetCode(10):正则表达式匹配 Regular Expression Matching(Java)

2019.4.20 #程序员笔试必备# LeetCode 从零单刷个人笔记整理(持续更新)

今天看了一下阿里的Java代码规范,发现if和else不带括号并不是简洁的一种表现,以后会好好加括号的。

这道题之前有在《剑指Offer》上做过原题(笔记传送门:#数据结构与算法学习笔记#剑指Offer50:正则表达式匹配(Java、C/C++)),没想到LeetCode再刷一次的时候,所用的递归方法居然不是最优方法了。第二次手撕明显也和第一次不懂看着答案写的逻辑不同了。没想到DP大法居然也可以破,太强大了简直刷新三观。

这道题大体思路有两种:

1.递归:

递归思路也比较顺畅,主要考察逻辑。设定两个标识指针sidx和pidx,每次递归进行匹配。

1.若sidx匹配完成,可能有两种情况:p也匹配完成(true)、p是’abc*……'类型,继续检查。

2.否则,若p先于s匹配完成,返回false。

3.否则,若元素的下一位是’*’,可能有两种情况:元素出现0次,或元素匹配并出现多次(包括1次),递归继续检查。

4.否则,若元素匹配则继续检查,若不匹配则返回false。

2.动态规划:

动态规划的思路又分两种:自头向尾和自尾向头。

自头向尾:

1.建立dp数组,dp[sidx][pidx]表示在长为sidx的s的子串与长为pidx的p的子串的匹配情况。预设dp[0][0] = true(s和p都为空时成立)。

2.处理当s为空串的情况,此时p只有一种情况能够成立,即“abc*……”。奇数字位符全为false,偶数每隔两个字符检查是否是’*’,若是则其是否成立取决于上一个偶数项的情况

3.更新dp数组,注意dp[sidx][pidx]对应s和p的下标为sidx-1和pidx-1。

当前元素匹配时,dp[sidx][pidx]取决于dp[sidx - 1][pidx - 1]

p当前元素为’‘时,如果’'的元素不匹配,则只可能是元素出现0次的情况,dp[sidx][pidx]取决于dp[sidx][pidx - 2]。

p当前元素为’‘时,如果’'的元素匹配,可能有两种情况:元素出现0次(取决于dp[sidx][pidx - 2])、出现多次(dp[sidx - 1][pidx],包含出现1次(取决于dp[sidx][pidx - 1]))

4.返回dp[s.length()][p.length()]对应情况。

自尾向头:

1.建立dp数组,dp[sidx][pidx]表示从尾向头长指针匹配至sidx与pidx位置的情况。预设dp[s.length()][p.length()]起始位true,当s和p均空时,可以匹配。

2.自尾向头更新dp。

若pidx下一个元素是’*’,可能有两种情况:元素出现0次(dp[sidx][pidx]取决于dp[sidx][pidx + 2]),元素匹配且出现多次(dp[sidx][pidx]取决于dp[sidx + 1][pidx],包含出现一次)

若pidx下一个元素不是’*’,且元素匹配,则dp[sidx][pidx]取决于上一指针匹配情况dp[sidx + 1][pidx + 1]

3.返回dp[0][0]对应情况。


传送门:正则表达式匹配

Given an input string (s) and a pattern §, implement regular expression matching with support for ‘.’ and ‘*’.

‘.’ Matches any single character.
‘*’ Matches zero or more of the preceding element.
The matching should cover the entire input string (not partial).

Note:

s could be empty and contains only lowercase letters a-z.
p could be empty and contains only lowercase letters a-z, and characters like . or *.

给定一个字符串 (s) 和一个字符模式 §。实现支持 ‘.’ 和 ‘*’ 的正则表达式匹配。

‘.’ 匹配任意单个字符。
‘*’ 匹配零个或多个前面的元素。
匹配应该覆盖整个字符串 (s) ,而不是部分字符串。

说明:

s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 *。

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

示例 2:
输入:
s = "aa"
p = "a*"
输出: true
解释: '*' 代表可匹配零个或多个前面的元素, 即可以匹配 'a' 。因此, 重复 'a' 一次, 字符串可变为 "aa"。

示例 3:
输入:
s = "ab"
p = ".*"
输出: true
解释: ".*" 表示可匹配零个或多个('*')任意字符('.')。

示例 4:
输入:
s = "aab"
p = "c*a*b"
输出: true
解释: 'c' 可以不被重复, 'a' 可以被重复一次。因此可以匹配字符串 "aab"。

示例 5:
输入:
s = "mississippi"
p = "mis*is*p*."
输出: false


/**
 *
 * Given an input string (s) and a pattern (p), implement regular expression matching with support for '.' and '*'.
 * 给定一个字符串 (s) 和一个字符模式 (p)。实现支持 '.' 和 '*' 的正则表达式匹配。
 *
 */

public class RegularExpressionMatching {
   

    //递归匹配
    public boolean isMatch(String s, String p) {
   
        return Solution(s, p, 0, 0);
    }

    public boolean Solution(String s, String p, int sidx, int pidx){
   
        //若sidx匹配完成,可能有两种情况:p也匹配完成(true)、p是'a*b*c*……'类型,继续检查。
        if(sidx >= s.length()){
   
            if(pidx < p.length() - 1 && p.charAt(pidx + 1) == '*'){
   
                return Solution(s, p, sidx, pidx + 2);
            }
            else
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值