一、题目还原
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘’ 的正则表达式匹配。
‘.’ 匹配任意单个字符
'’ 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
说明:
s 可能为空,且只包含从 a-z 的小写字母。
p 可能为空,且只包含从 a-z 的小写字母,以及字符 . 和 。
示例 1:
输入:
s = “aa”
p = “a”
输出: false
解释: “a” 无法匹配 “aa” 整个字符串。
示例 2:
输入:
s = “aa”
p = "a"
输出: true
解释: 因为 ‘’ 代表可以匹配零个或多个前面的那一个元素, 在这里前面的元素就是 ‘a’。因此,字符串 “aa” 可被视为 ‘a’ 重复了一次。
示例 3:
输入:
s = “ab”
p = "."
输出: true
解释: "." 表示可匹配零个或多个(’’)任意字符(’.’)。
示例 4:
输入:
s = “aab”
p = “cab”
输出: true
解释: 因为 '’ 表示零个或多个,这里 ‘c’ 为 0 个, ‘a’ 被重复一次。因此可以匹配字符串 “aab”。
示例 5:
输入:
s = “mississippi”
p = "misisp."
输出: false
二、解题思路
① EdgeCase:只有两个都为空才会match
② 初始判断:要么p和s第一个字符相等,要么p的第一个字符为’.’,才会首字符match
③ 分情况考虑,p的第二字符是不是“*”,如果是,则匹配s和p的第二位之后的字符串是否匹配或者首字符匹配,s的第一位之后和p是否匹配;如果不是就比较s的第一位之后和p的第一位之后的字符串是否匹配
三、代码展示
① main函数
public static void main(String[] args) {
String s = "adnaaasf";
String p = "a.nd*a.*";
System.out.println(isMatch(s,p));
}
② isMatch方法函数
public static boolean isMatch(String s, String p) {
//EdgeCase:只有两个都为空才会match
if(null == p || p.length() == 0){
return null == s || s.length() == 0;
}
//要么第一个字符相等,要么p的第一个字符为'.',才会首字符match
boolean init = s.length() > 0 && (s.charAt(0) == p.charAt(0) || p.charAt(0) == '.');
//p的第二个字符为'*'的时候,需要判断s和p第二个字符之后的是否匹配或者首字符match,s第一个字符之后与p是否match
if(p.length() > 1 && p.charAt(1) == '*'){
return isMatch(s,p.substring(2)) || (init && isMatch(s.substring(1),p));
}else{
//剩余的就是看s和p第一个字符相等之后剩余的是否match
return init && isMatch(s.substring(1),p.substring(1));
}
}
控制台输出:
true
Process finished with exit code 0
四、自我总结
不知不觉已经做到了LeetCode的第十题,难度为困难,博主在刚拿到题目的时候有点一脸懵逼,这不就是Java中String.matches(s)
吗?但是在刷题的过程中如果这么投机取巧的话肯定是得不到算法上的提升。分析了一波题目后感觉暴力递归逐一进行比较的可行性比较大,于是按照思路把递归算法写完,但是博主还是有自知之明的,这样的暴力效率一定是大打折扣的,果不其然,提交结果依旧惨淡。
看了官方题解之后意外发现自己写的这种称谓回溯法,博主于是去网上搜关于回溯和递归的区别,看到一篇博客讲的通俗易懂:
后面博主会去尝试弄懂动态规划的思想,优化自己的算法!
- 博主最近也将刷题的代码上传到github中,欢迎各位大佬们指点一二
Github仓库地址:https://github.com/w735937076/LeetCode