Interleaving String

Interleaving String

问题:

Given s1s2s3, find whether s3 is formed by the interleaving of s1 and s2.

思路:

  dfs肯定能解决 但是肯定会超时

  动态规划方程dp[i][j] == true only dp[i-1][j]&&s1.charAt(i)==s3.charAt(i+j) or dp[i][j-1] && s2.charAt(j) == s3.charAt(i+j)在刚了网上的答案后,才豁然开朗。

参考答案后我写的代码:

public class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
        if(s1 == null || s2 == null || s3 == null)  return true;
        if(s1.length() + s2.length() != s3.length()) return false;
        int m = s1.length();
        int n = s2.length();
        boolean[][] flag = new boolean[m+1][n+1];
        flag[0][0] = true;
        for(int i = 1; i <= m; i++)
        {
            if(flag[i-1][0])
            {
                if(s1.substring(0,i).equals(s3.substring(0,i)))
                {
                    flag[i][0] = true;
                }
            }
        }
        for(int j = 1; j <= n; j++)
        {
            if(flag[0][j-1])
            {
                if(s2.substring(0,j).equals(s3.substring(0,j)))
                {
                    flag[0][j] = true;
                }
            }
        }
        for(int i = 1; i <= m; i++)
        {
            for(int j = 1; j <= n; j++)
            {
                if(flag[i][j-1])
                {
                    if(s2.charAt(j-1) == s3.charAt(i+j-1))
                        flag[i][j] = true;
                }
                if(flag[i-1][j])
                {

                    if(s1.charAt(i-1) == s3.charAt(i+j-1))
                        flag[i][j] = true;
                }
            }
        }
        return flag[m][n];
    }
}
View Code

别人代码1:(递归+memory)

// Solution1: Recursion with memory
    public static boolean isInterleave1(String s1, String s2, String s3) {
        if (s1 == null || s2 == null || s3 == null) {
            return false;
        }

        int len1 = s1.length();
        int len2 = s2.length();
        int len3 = s3.length();

        // The length is not equal, just return false.
        if (len1 + len2 != len3) {
            return false;
        }

        int[][][] memory = new int[len1 + 1][len2 + 1][len3 + 1];
        for (int i = 0; i <= len1; i++) {
            for (int j = 0; j <= len2; j++) {
                for (int k = 0; k <= len3; k++) {
                    memory[i][j][k] = -1;
                }
            }
        }

        return recMemory(s1, 0, s2, 0, s3, 0, memory);
    }

    public static boolean recMemory(String s1, int index1, String s2,
            int index2, String s3, int index3, int[][][] memory) {
        int len1 = s1.length();
        int len2 = s2.length();
        int len3 = s3.length();

        if (index3 == len3 && index1 == len1 && index2 == len2) {
            return true;
        }

        if (memory[index1][index2][index3] != -1) {
            return memory[index1][index2][index3] == 1;
        }

        // 第一个字符,有2种可能:来自s1, 或是来自s2
        boolean ret = false;
        if (index1 < len1 && s1.charAt(index1) == s3.charAt(index3)) {
            ret = recMemory(s1, index1 + 1, s2, index2, s3, index3 + 1, memory);
        }

        // 如果不成功(首字母不来自于s1),尝试另一种可能
        if (!ret && index2 < len2 && s2.charAt(index2) == s3.charAt(index3)) {
            ret = recMemory(s1, index1, s2, index2 + 1, s3, index3 + 1, memory);
        }

        memory[index1][index2][index3] = ret ? 1 : 0;
        return ret;
    }

    // Solution2: Recursion with memory
    // 思考了一下看了一下过去的代码,发现其实我们用不到三维数组,因为len1 + len2 = len3,
    // 所以第三维根本可以省略嘛
    public static boolean isInterleave2(String s1, String s2, String s3) {
        if (s1 == null || s2 == null || s3 == null) {
            return false;
        }

        int len1 = s1.length();
        int len2 = s2.length();
        int len3 = s3.length();

        // The length is not equal, just return false.
        if (len1 + len2 != len3) {
            return false;
        }

        int[][] memory = new int[len1 + 1][len2 + 1];
        for (int i = 0; i <= len1; i++) {
            for (int j = 0; j <= len2; j++) {
                memory[i][j] = -1;
            }
        }

        return recMemory2(s1, 0, s2, 0, s3, 0, memory);
    }
View Code

别人代码2:动态规划

public class Solution {
    public boolean isInterleave1(String s1, String s2, String s3) {
        if (s1 == null || s2 == null || s3 == null) {
            return false;
        }
        
        int len1 = s1.length();
        int len2 = s2.length();
        int len3 = s3.length();
        
        if (len1 + len2 != len3) {
            return false;
        }
        
        boolean[][] D = new boolean[len1 + 1][len2 + 1];
        
        for (int i = 0; i <= len1; i++) {
            for (int j = 0; j <= len2; j++) {
                D[i][j] = false;
                if (i == 0 && j == 0) {
                    D[i][j] = true;
                } else if (i == 0) {
                    D[i][j] = s2.charAt(j - 1) == s3.charAt(i + j - 1) && D[i][j - 1];
                } else if (j == 0) {
                    D[i][j] = s1.charAt(i - 1) == s3.charAt(i + j - 1) && D[i - 1][j];
                } else {
                    D[i][j] |= s2.charAt(j - 1) == s3.charAt(i + j - 1) && D[i][j - 1];
                    D[i][j] |= s1.charAt(i - 1) == s3.charAt(i + j - 1) && D[i - 1][j];
                }
            }
        }
        
        return D[len1][len2];
    }
    
    public boolean isInterleave(String s1, String s2, String s3) {
        if (s1 == null || s2 == null || s3 == null) {
            return false;
        }
        
        int len1 = s1.length();
        int len2 = s2.length();
        int len3 = s3.length();
        
        if (len1 + len2 != len3) {
            return false;
        }
        
        boolean[][] D = new boolean[len1 + 1][len2 + 1];
        
        for (int i = 0; i <= len1; i++) {
            for (int j = 0; j <= len2; j++) {
                D[i][j] = false;
                if (i == 0 && j == 0) {
                    D[i][j] = true;
                    continue;
                }
                
                if (i != 0) {
                    D[i][j] |= s1.charAt(i - 1) == s3.charAt(i + j - 1) && D[i - 1][j];
                }
                
                if (j != 0) {
                    D[i][j] |= s2.charAt(j - 1) == s3.charAt(i + j - 1) && D[i][j - 1];
                }
            }
        }
        
        return D[len1][len2];
    }
}
View Code

 学习之处:

  • 加入递归的想法很容易想啊,递归+memory和dp的方法时间复杂度一致,只是在空间上浪费了好多,在面试里面想不出来dp可以用dfs+memory解决不失为一个好的方法。
  • 字符串匹配常用的方法就是动态规划解决问题。
  • 对于两个字符串的匹配问题,就是母串从小到大 左右是否可以由子串组成
  • 对于说那个字符串的匹配问题,就是母串从小到大 左右是否由子串组成
  • 停!不知道动态规划方程式什么,可以先写dfs,写完dfs反推就可以得到动态规划方程了。(灵光一现的结论,明后天写代码尝试一下)

posted on 2015-03-27 23:10  zhouzhou0615  阅读(171)  评论(0编辑  收藏  举报

导航