Wildcard Matching

题目链接:
https://leetcode.com/problems...
这道题还是可以用"Regular Expression Matching" 的方法,用2d的dp数组来解,空间复杂度较高。

    public boolean isMatch(String s, String p) {
        /* boolean dp[len(s) + 1][len(p) + 1] 
         * dp[i+1][j+1] means if s[0, i] match p[0, j]
         * function: dp[i+1][j+1] 
         *         a. p[j] = * => 1. empty: dp[i+1][j]
         *                        2. one: dp[i][j]
         *                        3. multiple: dp[i][j+1]
         *         b. p[j] = s[i] | p[j] = ? => dp[i][j]
         * start: dp[0][0] = true, dp[0][j+1] = dp[0][j] & p[j] = *
         * result: dp[len(s)][len(p)]
         */
         
         boolean[][] dp = new boolean[s.length() + 1][p.length() + 1];
         // start
         dp[0][0] = true;
         for(int j = 0; j < p.length(); j++) dp[0][j+1] = dp[0][j] & (p.charAt(j) == '*');
         
         // loop
         for(int i = 0; i < s.length(); i++) {
             for(int j = 0; j < p.length(); j++) {
                 if(p.charAt(j) == '*') {
                     dp[i+1][j+1] = dp[i+1][j] | dp[i][j] | dp[i][j+1];
                 }
                 else if(p.charAt(j) == s.charAt(i) || p.charAt(j) == '?') dp[i+1][j+1] = dp[i][j];
             }
         }
         return dp[s.length()][p.length()];
    }

另一种思路是greedy,只需要O(1)的空间。和regular expression不同,这道题的star符号和前面的character没有关系,不需要一起考虑。而且star是可以匹配任何string的,"aa", "ab"都可以。所以check是否匹配的时候,只需要按位一个一个判断就行了。用两个指针i和j分别扫描s和p,loop过程中有以下几种情况:

  1. 成功匹配:s[i] == p[j] or p[j] == '?' => i++, j++

  2. 出现星号:p[j] == '*'

  3. 匹配不上:return false

第二种情况比较麻烦,单独讨论一下。

  1. p[j]匹配0个 => j++

  2. p[j]匹配1个 => j++, i += 1

  3. p[j]匹配2个 => j++, i += 2
    ......

可以看出来,要尝试不同的匹配个数,所以要加两个指针保存之前出现star时的i和j:stari和starj。那么每次碰到'*'的时候,都保存一下,先试下匹配0个的时候后面的字符是否可以匹配上,如果不行再试1个,2个。。重复这个过程。
以s的长度为loop的终点,所以最后还要考虑一下p后面还有多的'*'的情况。

时间复杂度度

最好的情况下,没有star或者所有star都匹配0个字符,O(M+N)。
最坏的情况下,star间隔出现且每个star都要匹配很多字符,设一个star平均匹配s里面x个字符,O(xN + M) = O(M*N)。其中,M是s的长度,N是p的长度。

    public boolean isMatch(String s, String p) {
        int i = 0, j = 0;
        int stari = -1, starj = -1;
        while(i < s.length()) {
            // 1. match
            if(j < p.length() && (s.charAt(i) == p.charAt(j) || p.charAt(j) == '?')) {
                i++; j++;
            }
            // 2. star
            else if(j < p.length() && p.charAt(j) == '*') {
                // first match 0
                stari = i;
                starj = ++j;
            }
            // different number that '*' matches 
            else if(stari != -1) {
                // match number +1
                i = ++stari;
                j = starj;
            }
            // 3. not match and no star
            else return false;
        }
        // remove last '*' in p
        while(j < p.length() && p.charAt(j) == '*') j++;
        
        return j == p.length();
    }

lulouch13
13 声望6 粉丝