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