LeetCode刷題筆記(十)正則表示式匹配
阿新 • • 發佈:2019-01-03
給定一個字串 (s
) 和一個字元模式 (p
)。實現支援 '.'
和 '*'
的正則表示式匹配。
'.' 匹配任意單個字元。 '*' 匹配零個或多個前面的元素。
匹配應該覆蓋整個字串 (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
解法1:
class Solution { public boolean isMatch(String s, String p) { int slen = s.length(); int plen = p.length(); if (slen == 0 && plen == 0) return true; char c0 = getChar(s, 0); char p0 = getChar(p, 0), char p1 = getChar(p, 1); if (match(c0, p0) || p1 == '*') { if (p1 != '*') { if (slen == 0) return false; return isMatch(s.substring(1), p.substring(1)); //遞迴判斷下一個字元 } // if p1 is *, * means 0 ~ n int i = 0; boolean ret = isMatch(s.substring(0), p.substring(2)); // try 0 if (ret) return ret; while (i < slen && match(getChar(s, i), p0)) { ret = isMatch(s.substring(i+1), p.substring(2)); // try for every available position if (ret) return ret; i++; } } return false; } private boolean match(char a, char b) { //判斷字元相等 return a == b || b == '.'; } private char getChar(String s, int p) { //獲取字串的第n個字元 if (s.length() > n) { return s.charAt(n); } return 0; //超過索引就返回0 } }
這種演算法是遞迴呼叫方法,其中要注意的點有:獲取字串的第n個字元的時候超出範圍返回0,這樣子就不會出現遺漏;
時間複雜度:O(m*n);
空間複雜度:O(m*n)
解法2:
class Solution { public boolean isMatch(String s, String p) { // 標記數陣列 boolean[] match = new boolean[s.length() + 1]; // 初始化 Arrays.fill(match, false); // 假定最後的結果是匹配的 match[s.length()] = true; // 對模式串從後向前進行處理 for (int i = p.length() - 1; i >= 0; i--) { // 如果當前是* if (p.charAt(i) == '*') { // 匹配串從最後一個開始處理 for (int j = s.length() - 1; j >= 0; j--) { match[j] = match[j] || match[j + 1] && (p.charAt(i - 1) == '.' || s.charAt(j) == p.charAt(i - 1)); } i--; } // 如果不是* else { for (int j = 0; j < s.length(); j++) { match[j] = match[j + 1] && (p.charAt(i) == '.' || p.charAt(i) == s.charAt(j)); } match[s.length()] = false; } } return match[0]; } }
這是在網上找到的另外一直演算法,看得不是很理解
時間複雜度:O(m*n);
空間複雜度:O(m*n)