https://leetcode.com/problems/wildcard-matching/
Implement wildcard pattern matching with support for '?'
and '*'
.
'?' Matches any single character. '*' Matches any sequence of characters (including the empty sequence). The matching should cover the entire input string (not partial). The function prototype should be: bool isMatch(const char *s, const char *p) 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
解题思路:
这题和前面做过的 Regular Expression Matching 很像,思路也类似。用前面的思路去做,居然大数据的时候会超时。
public class Solution { public boolean isMatch(String s, String p) { return isMatchHelper(s, p, 0, 0); } public boolean isMatchHelper(String s, String p, int i, int j) { if(j >= p.length()) { return i >= s.length(); } if(i >= s.length()) { return j >= p.length(); } if(j == p.length() - 1) { return p.charAt(j) == '*' || p.charAt(j) == '?' || (i == s.length() - 1 && s.charAt(i) == p.charAt(j)); } if(s.charAt(i) == p.charAt(j) || p.charAt(j) == '?') { return isMatchHelper(s, p, i + 1, j + 1); } if(p.charAt(j) == '*') { while(j < p.length()) { if(p.charAt(j) != '*') { break; } j++; } if(j == p.length()) { return true; } while(i < s.length()) { if(isMatchHelper(s, p, i, j)) { return true; } i++; } } return false; } }
上面的超时,大数据的时候,估计是因为递归。下面用迭代做。
思路是一样的,遇到*的时候,就跳过下面连续的*,然后把i和j的下标保存,下面继续匹配。如果不匹配,i和j就退回保存的值,然后继续匹配。
public class Solution { public boolean isMatch(String s, String p) { int i = 0, j = 0, lastI = -1, lastJ = -1; while(i < s.length()) { if(j >= p.length()) { // 不能直接返回false,也要考虑退回的情况,比如"hi", "*?" if(lastI == -1) { return false; } lastI++; i = lastI; j = lastJ; continue; } if(s.charAt(i) == p.charAt(j) || p.charAt(j) == '?') { i++; j++; continue; } if(p.charAt(j) == '*') { // p一次性略过下面连续的* while(j < p.length() && p.charAt(j) == '*') { j++; } if(j == p.length()) { return true; } // 保存已用来在s中做*匹配的尝试 lastI = i; lastJ = j; // i++; continue; } if(s.charAt(i) != p.charAt(j)) { if(lastI == -1) { return false; } // 不匹配就退回,i取下一个值继续尝试 lastI++; i = lastI; j = lastJ; } } // s已经结束,除非j后面全是*,或者已经结束,不然不匹配 while(j < p.length()) { if(p.charAt(j) != '*') { return false; } j++; } return true; } }
update 2015/06/27:
再写一个超内存的dp方法,这个dp倒是很好理解,思路与Distinct Subsequences很像。
public class Solution { public boolean isMatch(String s, String p) { boolean[][] dp = new boolean[s.length() + 1][p.length() + 1]; dp[0][0] = true; for(int i = 1; i < s.length() + 1; i++) { dp[i][0] = false;//可以省略,默认值 } for(int i = 1; i < p.length() + 1; i++) { if(p.charAt(i - 1) == '*') { dp[0][i] = dp[0][i - 1]; } else { dp[0][i] = false;//默认值 } } for(int i = 1; i < s.length() + 1; i++) { for(int j = 1; j < p.length() + 1; j++) { if(s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '?') { dp[i][j] = dp[i - 1][j - 1]; } else if(p.charAt(j - 1) == '*') { dp[i][j] = dp[i - 1][j - 1] || dp[i][j - 1] || dp[i - 1][j]; } else { dp[i][j] = false;//默认值 } } } return dp[s.length()][p.length()]; } }