(Java)LeetCode-44.Wildcard Matching
2016-09-20 15:46
337 查看
Implement wildcard pattern matching with support for
这道题刚开始看的时候,以为是第十题的简化版本,于是复习了一下该题思路,写起来蛮简单的。
但是居然超时了。。谁家面试的时候出这么难题啊。。最近遇到好多难题(两个字符串距离,最大值的最小值,最短路径blabla..),血条空了
后来在网上看到一个思路,用的回溯算法。链接如下 http://www.cnblogs.com/felixfang/p/3708999.html
思路是(摘抄):
超时原因在于即便使用了带记录的递归,对于p上的每一个'*',依然需要考虑'*' 匹配之后字符的所有情况,比如p = "c*ab*c",s = "cddabbac"时,遇到第一个'*',我们需要用递归处理p的剩余部分"ab*c" 和s的剩余部分"ddabbac"的所有尾部子集匹配。也就是:"ab*c"和"ddabbac","ab*c" 和"dabbac"的匹配,"ab*c" 和"abbac"的匹配,... ,"ab*c" 和"c"的匹配,"ab*c" 和"\0"的匹配。
遇到第二个'*',依然如此。每一个'*'都意味着p的剩余部分要和s的剩余部分的所有尾子集匹配一遍。然而,我们如果仔细想想,实际上,当p中'*'的数量大于1个时,我们并不需要像上面一样匹配所有尾子集。
依然以 p = "c*ab*c",s = "cddabbac"为例。
对于p = "c*ab*c",我们可以猜想出它可以匹配的s应该长成这样: "c....ab.....c",省略号表示0到任意多的字符。我们发现主要就是p的中间那个"ab"比较麻烦,一定要s中的'ab'来匹配,因此只要s中间存在一个"ab",那么一切都可以交给后面的'*'了。
所以说,当我们挨个比较p和s上的字符时,当我们遇到p的第一个'*',我们实际只需要不断地在s的剩余部分找和'ab'匹配的部分。
换言之,我们可以记录下遇到*时p和s的位置,记为presp和press,然后挨个继续比较*(++p)和*(++s);如果发现*p != *s,就回溯回去,p = presp,s = press+1, ++press;直到比较到末尾,或者遇到了下一个'*',如果遇到了下一个'*',说明 "ab"部分搞定了,下面的就交给第二个'*'了;如果p和s都到末尾了,那么就返回true;如果到末尾了既没遇到新的'*',又还存在不匹配的值,press也已经到末尾了,那么就返回false了。
这样的思路和上面的递归比起来,最大的区别就在于:
遇到'*',我们只考虑遇到下一个'*'前的子问题,而不是考虑一直到末尾的子问题。从而避免大量的子问题计算。
我们通过记录 presp和press,每次回溯的方法,避免使用递归。
不过他是用C++写的,读懂其思路后,改写为Java版本,即可AC,代码如下
public class Solution {
public boolean isMatch(String s, String p) {
int is = 0;
int ip = 0;
int press = 0;
int presp = 0;
boolean backstrack = false;
for( is = 0; is < s.length(); ){
if( ip == p.length()){
if(backstrack == false){
return false;
}else if(p.charAt(p.length()-1) == '*'){
return true;
}
else {
ip = presp;
is = ++press;
}
}
if(p.charAt(ip) == '?'){
is++;
ip++;
}else if(p.charAt(ip) == '*'){
presp = ++ip;
press = is;
backstrack = true;
}else{
if(p.charAt(ip) == s.charAt(is)){
is++;
ip++;
}else if(backstrack){
ip = presp;
is = ++press;
}else{
return false;
}
}
}
while(ip <= p.length() - 1 && p.charAt(ip) == '*' ){
ip ++;
if( ip == p.length()){
break;
}
}
return ip == p.length();
}
public static void main(String[] args){
Solution sol = new Solution();
System.out.println(sol.isMatch("aa", "a"));
System.out.println(sol.isMatch("aa", "aa"));
System.out.println(sol.isMatch("aaa", "aa"));
System.out.println(sol.isMatch("aa", "*"));
System.out.println(sol.isMatch("aa", "a*"));
System.out.println(sol.isMatch("ab", "?*"));
System.out.println(sol.isMatch("aab", "c*a*b"));
System.out.println(sol.isMatch("ab", "*a"));
System.out.println(sol.isMatch("hi", "*?"));
}
}
'?'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
这道题刚开始看的时候,以为是第十题的简化版本,于是复习了一下该题思路,写起来蛮简单的。
但是居然超时了。。谁家面试的时候出这么难题啊。。最近遇到好多难题(两个字符串距离,最大值的最小值,最短路径blabla..),血条空了
后来在网上看到一个思路,用的回溯算法。链接如下 http://www.cnblogs.com/felixfang/p/3708999.html
思路是(摘抄):
超时原因在于即便使用了带记录的递归,对于p上的每一个'*',依然需要考虑'*' 匹配之后字符的所有情况,比如p = "c*ab*c",s = "cddabbac"时,遇到第一个'*',我们需要用递归处理p的剩余部分"ab*c" 和s的剩余部分"ddabbac"的所有尾部子集匹配。也就是:"ab*c"和"ddabbac","ab*c" 和"dabbac"的匹配,"ab*c" 和"abbac"的匹配,... ,"ab*c" 和"c"的匹配,"ab*c" 和"\0"的匹配。
遇到第二个'*',依然如此。每一个'*'都意味着p的剩余部分要和s的剩余部分的所有尾子集匹配一遍。然而,我们如果仔细想想,实际上,当p中'*'的数量大于1个时,我们并不需要像上面一样匹配所有尾子集。
依然以 p = "c*ab*c",s = "cddabbac"为例。
对于p = "c*ab*c",我们可以猜想出它可以匹配的s应该长成这样: "c....ab.....c",省略号表示0到任意多的字符。我们发现主要就是p的中间那个"ab"比较麻烦,一定要s中的'ab'来匹配,因此只要s中间存在一个"ab",那么一切都可以交给后面的'*'了。
所以说,当我们挨个比较p和s上的字符时,当我们遇到p的第一个'*',我们实际只需要不断地在s的剩余部分找和'ab'匹配的部分。
换言之,我们可以记录下遇到*时p和s的位置,记为presp和press,然后挨个继续比较*(++p)和*(++s);如果发现*p != *s,就回溯回去,p = presp,s = press+1, ++press;直到比较到末尾,或者遇到了下一个'*',如果遇到了下一个'*',说明 "ab"部分搞定了,下面的就交给第二个'*'了;如果p和s都到末尾了,那么就返回true;如果到末尾了既没遇到新的'*',又还存在不匹配的值,press也已经到末尾了,那么就返回false了。
这样的思路和上面的递归比起来,最大的区别就在于:
遇到'*',我们只考虑遇到下一个'*'前的子问题,而不是考虑一直到末尾的子问题。从而避免大量的子问题计算。
我们通过记录 presp和press,每次回溯的方法,避免使用递归。
不过他是用C++写的,读懂其思路后,改写为Java版本,即可AC,代码如下
public class Solution {
public boolean isMatch(String s, String p) {
int is = 0;
int ip = 0;
int press = 0;
int presp = 0;
boolean backstrack = false;
for( is = 0; is < s.length(); ){
if( ip == p.length()){
if(backstrack == false){
return false;
}else if(p.charAt(p.length()-1) == '*'){
return true;
}
else {
ip = presp;
is = ++press;
}
}
if(p.charAt(ip) == '?'){
is++;
ip++;
}else if(p.charAt(ip) == '*'){
presp = ++ip;
press = is;
backstrack = true;
}else{
if(p.charAt(ip) == s.charAt(is)){
is++;
ip++;
}else if(backstrack){
ip = presp;
is = ++press;
}else{
return false;
}
}
}
while(ip <= p.length() - 1 && p.charAt(ip) == '*' ){
ip ++;
if( ip == p.length()){
break;
}
}
return ip == p.length();
}
public static void main(String[] args){
Solution sol = new Solution();
System.out.println(sol.isMatch("aa", "a"));
System.out.println(sol.isMatch("aa", "aa"));
System.out.println(sol.isMatch("aaa", "aa"));
System.out.println(sol.isMatch("aa", "*"));
System.out.println(sol.isMatch("aa", "a*"));
System.out.println(sol.isMatch("ab", "?*"));
System.out.println(sol.isMatch("aab", "c*a*b"));
System.out.println(sol.isMatch("ab", "*a"));
System.out.println(sol.isMatch("hi", "*?"));
}
}
相关文章推荐
- LeetCode 44:Wildcard Matching
- leetcode 44: Wildcard Matching
- [LeetCode] 44. Wildcard Matching
- Leetcode (44) Wildcard Matching
- LeetCode44 Wildcard Matching
- leetcode解题报告:44 Wildcard Matching
- Leetcode 44. Wildcard Matching
- [leetcode] 44. Wildcard Matching
- LeetCode 44. Wildcard Matching
- LeetCode 44 Wildcard Matching
- Java for LeetCode 044 Wildcard Matching
- LeetCode 44 - Wildcard Matching
- [leetcode-44]Wildcard Matching(java)
- [LeetCode]--44. Wildcard Matching
- [leetcode] 44 Wildcard Matching
- leetcode 10 Regular Expression Matching & 44 Wildcard Matching
- LeetCode(44) Wildcard Matching
- leetcode-44. Wildcard Matching
- leetcode 44. Wildcard Matching
- LeetCode 44. Wildcard Matching