PS:leetcode第10题和第44题是动态规划的类型的题,十分类似,可以放一起,当然第10题会难一些。
一、第10题 - 暴力递归
public static boolean isMatch(String str, String pattern) {
return process(str.toCharArray(), pattern.toCharArray(), 0, 0);
}
//给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。
// '.' 匹配任意单个字符
// '*' 匹配零个或多个前面的那一个元素
// 所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
public static boolean process(char[] str, char[] pattern, int si, int pi){
if (si == str.length && pi == pattern.length){
return true;
}
//pi没有来到终点位置
if (si == str.length){
return (pi + 1 < pattern.length && pattern[pi + 1] == '*') && process(str, pattern, si, pi + 2);
}
//si没有来到终点位置
if (pi == pattern.length){
return false;
}
//pi + 1 不是 *
if (pi + 1 >= pattern.length || pattern[pi + 1] != '*'){
return (str[si] == pattern[pi] || pattern[pi] == '.') && process(str, pattern, si + 1, pi + 1);
}
//pi + 1 是 *
//不管是 不相等 ?*变成0 还是相等?*变成0 都是这个逻辑
if (process(str, pattern, si, pi + 2)){
return true;
}
while (si < str.length && (str[si] == pattern[pi] || pattern[pi] == '.')){
//变成1个 si+1 pi+2 后面的自己去玩
//变成2个 si+2 pi+2 后面的自己去玩
if (process(str, pattern, si + 1, pi + 2)){
return true;
}
si++;
}
return false;
}
二、第10题 - 暴力递归 + 斜率优化
public static boolean isMatch(String str, String pattern) {
return process(str.toCharArray(), pattern.toCharArray(), 0, 0);
}
//给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。
// '.' 匹配任意单个字符
// '*' 匹配零个或多个前面的那一个元素
// 所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。
public static boolean process(char[] str, char[] pattern, int si, int pi){
if (si == str.length && pi == pattern.length){
return true;
}
//pi没有来到终点位置
if (si == str.length){
return (pi + 1 < pattern.length && pattern[pi + 1] == '*') && process(str, pattern, si, pi + 2);
}
//si没有来到终点位置
if (pi == pattern.length){
return false;
}
//pi + 1 不是 *
if (pi + 1 >= pattern.length || pattern[pi + 1] != '*'){
return (str[si] == pattern[pi] || pattern[pi] == '.') && process(str, pattern, si + 1, pi + 1);
}
//pi + 1 是 *
//si = 3 pi = 7
//si [3 4 5 6]
//pi [9 9 9 9]
//si = 2 pi = 7
//si 2 [3 4 5 6]
//pi 9 [9 9 9 9]
//si = 2 pi = 7 -> si = 3 pi = 7 + si = 2 pi = 9
//斜率优化
if ((str[si] == pattern[pi] || pattern[pi] == '.') && process(str, pattern, si + 1, pi)){
return true;
}
return process(str, pattern, si, pi + 2);
}
三、第10题 - 动态规划
public static boolean isMatch1(String s, String p) {
int n = s.length();
int m = p.length();
char[] str = s.toCharArray();
char[] pattern = p.toCharArray();
//0 ... n
//0 ... m
boolean[][] dp = new boolean[n + 1][m + 1];
dp[n][m] = true;
//填写最后一行
for (int pi = m - 1; pi >= 0; pi--) {
dp[n][pi] = (pi + 1 < pattern.length && pattern[pi + 1] == '*') && dp[n][pi + 2];
}
//最后一列不用填写 因为pi来到结束位置 但si没有来到结束位置 默认是false
//为什么要单独判断第二列 因为一个普遍位置依赖pi + 2列
//填写倒数第二列
//pattern只剩下一个字符 但0 ... n - 2 大于一个字符,那么这些位置不用填写 默认false
//但是需要判断[n - 1][m - 1]这个位置 如果相等或者pattern的这个位置"." 那么就是true 否则false
if (n > 0 && m > 0){
dp[n - 1][m - 1] = (str[n - 1] == pattern[m - 1] || pattern[m - 1] == '.');
}
for (int si = n - 1; si >= 0; si--) {
for (int pi = m - 2; pi >= 0; pi--) {
if (pi + 1 >= pattern.length || pattern[pi + 1] != '*'){
dp[si][pi] = (str[si] == pattern[pi] || pattern[pi] == '.') && dp[si + 1][pi + 1];
}else{
if ((str[si] == pattern[pi] || pattern[pi] == '.') && dp[si + 1][pi]){
dp[si][pi] = true;
}else{
dp[si][pi] = dp[si][pi + 2];
}
}
}
}
return dp[0][0];
}
四、第44题 - 暴力递归(会超时 哈哈哈)
//给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配。
// '?' 可以匹配任何单个字符。
//'*' 可以匹配任意字符串(包括空字符串)。
public static boolean isMatch10(String s, String p) {
return process10(s.toCharArray(), p.toCharArray(), 0, 0);
}
public static boolean process10(char[] str, char[] pattern, int si, int pi){
if (si == str.length && pi == pattern.length){
return true;
}
if (si == str.length){
return pattern[pi] == '*' && process10(str, pattern, si, pi + 1);
}
if (pi == pattern.length){
return false;
}
if (pattern[pi] != '*'){
return (str[si] == pattern[pi] || pattern[pi] == '?') && process10(str, pattern, si + 1, pi + 1);
}
//si 4 5 6 7 8 (9) 9 - 4 = 5个数
//pi *
for (int len = 0; len <= str.length - si; len++) {
if (process10(str, pattern, si + len, pi + 1)){
return true;
}
}
return false;
}
五、第44题 - 暴力递归 + 斜率优化(依然会超时 哈哈哈)
//给定一个字符串 (s) 和一个字符模式 (p) ,实现一个支持 '?' 和 '*' 的通配符匹配。
// '?' 可以匹配任何单个字符。
//'*' 可以匹配任意字符串(包括空字符串)。
public static boolean isMatch10(String s, String p) {
return process10(s.toCharArray(), p.toCharArray(), 0, 0);
}
public static boolean process10(char[] str, char[] pattern, int si, int pi){
if (si == str.length && pi == pattern.length){
return true;
}
if (si == str.length){
return pattern[pi] == '*' && process10(str, pattern, si, pi + 1);
}
if (pi == pattern.length){
return false;
}
if (pattern[pi] != '*'){
return (str[si] == pattern[pi] || pattern[pi] == '?') && process10(str, pattern, si + 1, pi + 1);
}
//斜率优化
if (process10(str, pattern, si + 1, pi)){
return true;
}
if (process10(str, pattern, si, pi + 1)){
return true;
}
return false;
}
六、第44题 - 动态规划
public static boolean isMatch11(String s, String p) {
int n = s.length();
int m = p.length();
char[] str = s.toCharArray();
char[] pattern = p.toCharArray();
boolean[][] dp = new boolean[n + 1][m + 1];
dp[n][m] = true;
for (int pi = m - 1; pi >= 0; pi--) {
dp[n][pi] = pattern[pi] == '*' && dp[n][pi + 1];
}
for (int si = n - 1; si >= 0; si--) {
for (int pi = m - 1; pi >= 0; pi--) {
if (pattern[pi] != '*'){
dp[si][pi] = (str[si] == pattern[pi] || pattern[pi] == '?') && dp[si + 1][pi + 1];
}else{
dp[si][pi] = dp[si + 1][pi] || dp[si][pi + 1];
}
}
}
return dp[0][0];
}