Idiot-maker

  :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

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()];
    }
}

 

posted on 2015-05-09 20:54  NickyYe  阅读(152)  评论(0编辑  收藏  举报