10. Regular Expression Matching

这道题的难点在于各种情况的讨论 dp[i][j]表示s的前i个字符能不能和p的前j个字符match上

如何运用之前的结果比如dp[i][j-1] dp[i-1][j]推得当前dp[i][j]结果

(1)如果当前的字符一样 则完全取决于(i-1,j-1)

(2)如果当前的P是“*” 如果P的前面一个字符等于S当前字符 可以是直接等于也可以是间接的“.”分为三种情况讨论

public class Solution {
    public boolean isMatch(String s, String p) {
        int m = s.length();
        int n = p.length();
        //dp(i,j) whether the first # of i element match with the first # of j element 
        boolean[][] dp = new boolean[m + 1][n + 1]; 

        //empty match 
        dp[0][0] = true;

        //base case
        for(int i = 2;i <= n;i++){
            //the dp[i][j-2]only requires when curP == '*'
            if(p.charAt(i-1) == '*'){
                dp[0][i] = dp[0][i-2];
            }
        }
        //Iteration
        for(int i = 1;i <= m;i++){
            for(int j = 1;j <= n;j++){
                char curS = s.charAt(i-1);
                char curP = p.charAt(j-1);
                if(curP == curS || curP == '.'){
                    dp[i][j] = dp[i-1][j-1];
                }
                else if(curP == '*'){
                    char prevP = p.charAt(j-2);
                    if(prevP == '.'||prevP == curS){
                        //'.'等价于preP == CurS 
                        //取1一个,取0个,无限match
                        dp[i][j] = dp[i][j-1]||dp[i][j-2]||dp[i-1][j];
                    }
                    else{
                        dp[i][j] = dp[i][j-2];
                    }
                }
            }
        }
        return dp[m][n];
    }
}

44. Wildcard Matching

p[i] == "*" 两种情况 取任意多个 看dp(i-1,j) 还有就是什么都不取 看dp(i,j) 同样的base case结合递推式里面的判断

条件写!可以说是LC10的简化版本

public class Solution {
    public boolean isMatch(String s, String p) {
        if (p == null || p.length() == 0) {
            return s == null || s.length() == 0;
        }

        int rows = s.length();
        int cols = p.length();

        boolean[][] dp = new boolean[rows + 1][cols + 1];

        dp[0][0] = true;
        for (int j = 1; j <= cols; j++) {
            if (p.charAt(j - 1) == '*') {
                dp[0][j] = dp[0][j - 1];
            }
        }

        for (int i = 1; i <= rows; i++) {
            for (int j = 1; j <= cols; j++) {
                if (p.charAt(j - 1) != '*') {
                    if (s.charAt(i - 1) == p.charAt(j - 1) || p.charAt(j - 1) == '?') {
                        dp[i][j] = dp[i - 1][j - 1];
                    }
                } else {
                    dp[i][j] = dp[i][j - 1] || dp[i - 1][j];
                }
            }
        }

        return dp[s.length()][p.length()];
    }
}

161. One Edit Distance

One edit 所以长度差最多为 1.然后分情况讨论 如果有一个字符mismatch 当两个string长度相等的时候 直接判断两个string 剩下的是否一致。 当两个string长度相差1的时候 只能有一个操作 而这个操作不能用在直接exchange element上面 所以只能是

删除字符操作这样 就需要保持 s.substr(i+1)和t(i)相等 比如ABCD 和 ACD. 如果没有mismatch 则判断是不是长度相差 1 这样

就是直接删除

/** One edit distance means that the strings have one different index 
 *  Edit the first version by deleting the duplicated code */
public class Solution {
    public boolean isOneEditDistance(String s, String t) {
        int len1 = s.length();
        int len2 = t.length();
        if(Math.abs(len1 - len2) > 1)return false;
        //check for mismatch
        for(int i = 0;i < Math.min(len1,len2);i++){
            if(s.charAt(i) != t.charAt(i)){
                if(len1 == len2){
                    return s.substring(i + 1).equals(t.substring(i + 1));
                }
                if(len1 > len2){
                    return s.substring(i + 1).equals(t.substring(i));
                }
                else{
                    return s.substring(i).equals(t.substring(i + 1));
                }
            }
        }
        //if there are no mismatch then the two strings have 1 edit distance only
        //if the length difference is 1
        return Math.abs(len1 - len2) == 1;
    }

}

72. Edit Distance

follow up问题可以看 http://blog.csdn.net/linhuanmars/article/details/24213795

注意到这类问题在定义DP(i,j)的时候都是前i个和前j个匹配 是元素的个数 然后这里还是借鉴了前面的结果 加1或者替换 加和

删除是镜像的 所以只考虑加就行了

public class Solution {
    public int minDistance(String word1, String word2) {
        int len1 = word1.length();
        int len2 = word2.length();
        int[][] dis = new int[len1+1][len2+1];
        //base case 
        dis[0][0] = 0;
        for(int i = 1;i <= len2;i++){
            dis[0][i] = i;
        }
        for(int i =1 ;i <= len1;i++){
            dis[i][0] = i; 
        }
        //Iteration 
        for(int i = 1;i < len1+1;i++){
            for(int j = 1;j < len2+1;j++){
                if(word1.charAt(i-1) == word2.charAt(j-1)){dis[i][j] = dis[i-1][j-1];}
                else{
                    dis[i][j] = Math.min(Math.min(dis[i][j-1] + 1,dis[i-1][j] + 1),dis[i-1][j-1]+1);
                }
            }
        }
        return dis[len1][len2];
    }
}

139. Word Break

We were given an dictionary contains words and find whether a string could be break into words constructed by

the given dictionary words only? We could also use the history result. Such as whether the first m element of

the string is breakable and how we extend the result to larger index m(m > n) We can check whether any words right

indexed with n exist in the dictionary and if there are DP[i] = D[j].

We can calculate the maximum length of the given strings to reduce some unnecessary search. Be patient with the index

public class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        //P[i] defines whether the first # i element is breakable 
        if(s == null || s.length() == 0) return false;
        int len = s.length();
        //Build a HashSet from the ArrayList and calculate the maximum Length among the strings of 
        HashSet<String> set = new HashSet();
        int maxLen = 0;
        for(String str : wordDict){
            set.add(str);
            maxLen = Math.max(maxLen,str.length());
        }
        boolean[] P = new boolean[len + 1];
        //Base case
        P[0] = true;
        //Iteration
        for(int i = 1;i <= len;i++){
            for(int j = Math.max(0,i - maxLen);j < i;j++){
                if(P[j] == false)continue;
                String sub = s.substring(j,i);
                if(set.contains(sub))P[i] = true;
            }
        }
        return P[len];
    }
}

97. Interleaving String

同样的是字符串组合能否成为第三个字符串问题 这里的DP不用是三维的 因为两个维度就可以确认匹配S3的前K个字符 利用当前S3的字符
是否和S1或者S2的字符匹配 然后借用前面的结果 (i-1,j)是否能match到相应的s3

时间复杂度是O(len1)*O(len2)

这道题也可以用一维的去做 http://blog.csdn.net/linhuanmars/article/details/24683159 只不过对我来说不太懂

/** memo(i,j) describe whether the first i element in s1 and the first s2 element in s2
 *  could form the first (i + j) th element in s3. We do not need another array to state the 
 *  relationship **/
public class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
        int l1 = s1.length();
        int l2 = s2.length();
        int l3 = s3.length();
        if((l1 + l2) != l3)return false;
        boolean[][] memo = new boolean[l1 + 1][l2 + 1];
        //base case
        memo[0][0] = true;
        for (int i = 1; i <= s1.length(); i++) {
           if(s3.charAt(i - 1) == s1.charAt(i - 1) && memo[i-1][0])
                 memo[i][0] = true;
        }

        for (int j = 1; j <= s2.length(); j++) {
            if(s3.charAt(j - 1) == s2.charAt(j - 1) && memo[0][j - 1])
                memo[0][j] = true;
        }

        //Iteration
        for(int i = 1;i <= l1;i++){
            for(int j = 1;j <= l2;j++){
                int k = i + j;
                if((s3.charAt(k - 1) == s1.charAt(i - 1) && memo[i - 1][j] || s3.charAt(k - 1) == s2.charAt(j - 1)&& memo[i][j - 1])){
                    memo[i][j] = true;
                }
            }
        }
      return memo[l1][l2];
    }
}

results matching ""

    No results matching ""