Leetcode44 Wildcard Matching
2015-08-07 12:10
309 查看
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
Solution1
最简单的是递归,在《剑指offer》里也有类似的题目,便是用递归来解决的public class Solution { public boolean isMatch(String s, String p) { return isMatch(s,p,0,0); } public boolean isMatch(String s,String p,int i,int j){ if(i==s.length()&&j==p.length()) return true; if(i>s.length()||j==p.length()) return false;//i已超出2个字符以上,或者j到了末尾但i还未结束 if(p.charAt(j)=='*') return isMatch(s,p,i,j+1)||isMatch(s,p,i+1,j+1)||isMatch(s,p,i+1,j); if(i==s.length()) return false; if(s.charAt(i)==p.charAt(j)||p.charAt(j)=='?') return isMatch(s,p,i+1,j+1); return false; } }
Solution2
解法一的递归极其低效,虽然能解,但是太耗时间。这里换一种递归方法public class Solution { public boolean isMatch(String s, String p) { return isMatch(s,p,0,0); } public boolean isMatch(String s,String p,int i,int j){ if(i==s.length()&&j==p.length()) return true; if(j==p.length()) return false; if(p.charAt(j)=='*'){ while(j<p.length()&&p.charAt(j)=='*') j++;//将'*'都跳过 if(j==p.length()) return true; if(p.charAt(j)!='?') while(i<s.length()&&s.charAt(i)!=p.charAt(j)) i++; if(i==s.length()) return false; return isMatch(s,p,i+1,j+1)||isMatch(s,p,i+1,j); } if(i==s.length()) return false; if(s.charAt(i)==p.charAt(j)||p.charAt(j)=='?') return isMatch(s,p,i+1,j+1)||((j>0&&p.charAt(j-1)=='*')?isMatch(s,p,i+1,j):false); return (j>0&&p.charAt(j-1)=='*')?isMatch(s,p,i+1,j):false; } }
Solution3
解法二比解法一要好很多,主要是跳过了星号的判断,可以节省不少时间,但是递归仍然重复了很多次判断,这时候必须考虑到动态规划的解法了。一般说来,递归和动态规划有着明显的区别:递归往往都是从前至后或者从上往下(比如二叉树里面),而动态规划则往往都是从后往前或者从下往上(指思考过程,实际的运行过程仍然是从前往后从顶往下的,因为要记录中间过程)。动态规划的好处是在从后往前或从下往上的过程中,实际可以记录一些中间过程。这样便省去了很多重复过程。
public class Solution { public boolean isMatch(String s, String p) { int m = s.length(); int n = p.length(); boolean[][] dp = new boolean[m+1][n+1];//dp[i][j]为s中的前i段能匹配到p中j处 dp[0][0] = true; for(int j=0;j<n;j++){ dp[0][j+1] = dp[0][j]&&(p.charAt(j)=='*'); for(int i=0;i<m;i++){ if(p.charAt(j)=='*') dp[i+1][j+1] = dp[i+1][j]||dp[i][j]||dp[i][j+1];//此处的if-else语句便是本题动态规划的递推关系式 else dp[i+1][j+1] = dp[i][j]&&(p.charAt(j)=='?'||p.charAt(j)==s.charAt(i)); } } return dp[m] ; } }
Solution4
用滚动数组将解法三中的递推数组进一步简化为一维数组public class Solution { public boolean isMatch(String s, String p) { int m = s.length(); int n = p.length(); boolean[] dp = new boolean[m+1]; dp[0] = true; for(int j=0;j<n;j++){ if(p.charAt(j)=='*') for(int i=0;i<m;i++) dp[i+1] = dp[i+1]||dp[i]; else for(int i=m-1;i>=0;i--) dp[i+1] = dp[i]&&(p.charAt(j)=='?'||p.charAt(j)==s.charAt(i)); dp[0] = dp[0]&&(p.charAt(j)=='*');//这句话必须放在末尾 } return dp[m]; } }
Solution5
还有一种更精妙绝伦的解法。本质上是回溯法,但不需要递归,并且比递归效率高出很多。非递归的回溯解法
相关文章推荐
- leetcode 179 Largest Number
- leetcode 24 Swap Nodes in Pairs
- leetcode 2 Add Two Numbers 方法1
- leetcode 2 Add Two Numbers 方法2
- [LeetCode]47 Permutations II
- [LeetCode]65 Valid Number
- [LeetCode]123 Best Time to Buy and Sell Stock III
- [LeetCode] String Reorder Distance Apart
- [LeetCode] Sliding Window Maximum
- [LeetCode] Find the k-th Smallest Element in the Union of Two Sorted Arrays
- [LeetCode] Determine If Two Rectangles Overlap
- [LeetCode] A Distance Maximizing Problem
- leetcode_linearList
- leetcode_linearList02
- LeetCode[Day 1] Two Sum 题解
- LeetCode[Day 2] Median of Two Sorted Arrays 题解
- LeetCode[Day 3] Longest Substring Without... 题解
- LeetCode [Day 4] Add Two Numbers 题解
- LeetCode [Day 5] Longest Palindromic Substring 题解
- LeetCode [Day 6] ZigZag Conversion 题解