10. Regular Expression Matching
Implement regular expression matching with support for '.'
and '*'
.
'.' Matches any single character. '*' Matches zero or more of the preceding element. Some examples: isMatch("aa","a") → false isMatch("aa","aa") → true isMatch("aaa","aa") → false isMatch("aa", "a*") → true isMatch("aa", ".*") → true isMatch("ab", ".*") → true isMatch("aab", "c*a*b") → true
class Solution { public boolean isMatch(String s, String p) { return isMatch(s, 0, p, 0); } private boolean isMatch(String s, int si, String p, int pi) { if (pi == p.length()) return si == s.length(); if (pi + 1 < p.length() && p.charAt(pi + 1) == '*') //if followed by star { if (si == s.length()) return isMatch(s, si, p, pi + 2); if (isMatch(s, si, p, pi + 2)) //if can skip current * pattern return true; if (s.charAt(si) == p.charAt(pi) || p.charAt(pi) == '.')// cannot skip * pattern, must match return isMatch(s, si + 1, p, pi); return false; /* The code above is optimized from this TLE implementation. if(si == s.length()) return isMatch(s, si, p, pi+2); if(s.charAt(si) == p.charAt(pi) || p.charAt(pi) == '.'){ //if s match p return isMatch(s, si+1, p, pi) || //case1: skip current char in s isMatch(s, si, p, pi+2) || //case2: skip current two chars in p isMatch(s, si+1, p, pi+2); //case3: skip current char in s and current two chars in p } else return isMatch(s, si, p, pi+2); //else must skip current two chars in p */ } else { if (si == s.length()) return false; if (s.charAt(si) == p.charAt(pi) || p.charAt(pi) == '.') return isMatch(s, si + 1, p, pi + 1); return false; } } }
44. Wildcard Matching
Implement wildcard pattern matching with support for '?'
and '*'
.
'?' Matches any single character. '*' Matches any sequence of characters (including the empty sequence). Some examples: isMatch("aa","a") → false isMatch("aa","aa") → true isMatch("aaa","aa") → false isMatch("aa", "*") → true isMatch("aa", "a*") → true isMatch("ab", "?*") → true isMatch("aab", "c*a*b") → false
Slightly modified the code for Regular Expression Matching, you will get a TLE solution.
class Solution { public boolean isMatch(String s, String p) { return isMatch(s, 0, p, 0); } private boolean isMatch(String s, int si, String p, int pi) { if (pi == p.length()) return si == s.length(); if (p.charAt(pi) == '*') { if (si == s.length()) return isMatch(s, si, p, pi + 1); if (isMatch(s, si, p, pi + 1) || isMatch(s, si + 1, p, pi)) return true; return false; } else { if (si == s.length()) return false; if (s.charAt(si) == p.charAt(pi) || p.charAt(pi) == '?') return isMatch(s, si + 1, p, pi + 1); return false; } } }
2D DP solution. O(MN) complexity and space.
DP[stringRow][patternCol] indicated whether s.substring(0,stringRow) can match p.substring(0,patternCol)
class Solution { public boolean isMatch(String s, String p) { int row = s.length(), col = p.length(); boolean[][] dp = new boolean[row + 1][col + 1]; dp[0][0] = true; //"" can match "" for (int r = 1; r <= row; r++) { dp[r][0] = false; //string with length cannot match "" } for (int c = 1; c <= col; c++) { if (p.charAt(c - 1) == '*') { dp[0][c] = true; //"" can match all stars until ... } else { break; //until it sees a non-star } } for (int strR = 1; strR <= row; ++strR) { //for the string s.substring(0,strR), iterate through patterns char sCurrent = s.charAt(strR - 1); for (int patC = 1; patC <= col; ++patC) { char pCurrent = p.charAt(patC - 1); if (pCurrent != '*') { dp[strR][patC] = //when previous string can match previous pattern dp[strR - 1][patC - 1] && //check whether the incremental part matches. (sCurrent == pCurrent || pCurrent == '?'); } else { dp[strR][patC] = dp[strR - 1][patC] || //when previous string can match current pattern //when current string can match previous pattern then we don't need current * dp[strR][patC - 1]; } } } return dp[row][col]; } }
Linear Solution:
http://yucoding.blogspot.com/2013/02/leetcode-question-123-wildcard-matching.html
si is current string pointer.
pi is current pattern pointer.
match is the pointer for string already matched.
starIndex points to last star.
class Solution { public boolean isMatch(String s, String p) { int si = 0, pi = 0, match = 0, starIdx = -1; while (si < s.length()) { // advancing both pointers if (pi < p.length() && (p.charAt(pi) == '?' || s.charAt(si) == p.charAt(pi))) { si++; pi++; } // * found, only advancing p pointer else if (pi < p.length() && p.charAt(pi) == '*') { starIdx = pi; match = si; pi++; } // last p pointer was *, advancing string pointer else if (starIdx != -1) { pi = starIdx + 1; match++; si = match; } //current p pointer is not star, last patter pointer was not * //characters do not match else return false; } //check for remaining characters in p while (pi < p.length() && p.charAt(pi) == '*') pi++; return pi == p.length(); } }