Interleaving String
Interleaving String
问题:
Given s1, s2, s3, 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]; } }
别人代码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); }
别人代码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]; } }
学习之处:
- 加入递归的想法很容易想啊,递归+memory和dp的方法时间复杂度一致,只是在空间上浪费了好多,在面试里面想不出来dp可以用dfs+memory解决不失为一个好的方法。
- 字符串匹配常用的方法就是动态规划解决问题。
- 对于两个字符串的匹配问题,就是母串从小到大 左右是否可以由子串组成
- 对于说那个字符串的匹配问题,就是母串从小到大 左右是否由子串组成
- 停!不知道动态规划方程式什么,可以先写dfs,写完dfs反推就可以得到动态规划方程了。(灵光一现的结论,明后天写代码尝试一下)
posted on 2015-03-27 23:10 zhouzhou0615 阅读(171) 评论(0) 编辑 收藏 举报