Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.
For example,
Given:
s1 =
s2 =
Given:
s1 =
"aabcc"
,s2 =
"dbbca"
,
When s3 =
When s3 =
"aadbbcbcac"
, return true.When s3 =
"aadbbbaccc"
, return false.
Solution1: 2D dp
“When you see string problem that is about subsequence or matching, dynamic programming method should come to your mind naturally. ”
这道题思路是,s1取一部分s2取一部分,看最后是否能匹配s3。
定义一个boolean二维数组dp[i][j]表示: s1取前i位,s2取前j位,是否能组成s3的前i+j位。
首先,假设s2为空,将s1每一位跟s3匹配放入dp[i][0];假设s1为空,将s2每一位跟s3匹配放入dp[0][j]。
如果不等就是False。
判断true的时候,第一个条件,新添加的字符,要等于s3里面对应的位( i + j 位),第二个条件,之前那个格子也要等于True
举个简单的例子s1 = ab, s2 = c, s3 = bbc ,假设s1已经取了2位,c还没取,此时是False(ab!=bb),我们取s2的新的一位c,即便和s3中的c相等,但是之前是False,所以这一位也是False。
同理,如果s1 = ab, s2 = c, s3=abc ,同样的假设,s1取了2位,c还没取,此时是True(ab==ab),我们取s2的新的一位c,和s3中的c相等,且之前这一位就是True,此时我们可以放心置True (abc==abc)。
时间上因为是一个二维动态规划,所以复杂度是O(m*n),m和n分别是s1和s2的长度。空间复杂度是O(m*n).
时间上因为是一个二维动态规划,所以复杂度是O(m*n),m和n分别是s1和s2的长度。空间复杂度是O(m*n).
public class Solution { public boolean isInterleave(String s1, String s2, String s3) { if(s1 == null || s2 == null || s3 == null) return false; if(s1.length() + s2.length() != s3.length()) return false; boolean[][] dp = new boolean[s1.length() + 1][s2.length() + 1]; dp[0][0] = true; for(int i = 1; i <= s1.length(); i++) { if(s1.charAt(i - 1) == s3.charAt(i - 1) && dp[i - 1][0]) { dp[i][0] = true; } } for(int j = 1; j <= s2.length(); j++) { if(s2.charAt(j - 1) == s3.charAt(j - 1) && dp[0][j - 1]) { dp[0][j] = true; } } for(int i = 1; i <= s1.length(); i++) { for(int j = 1; j <= s2.length(); j++) { char c = s3.charAt(i + j - 1); if(c == s1.charAt(i - 1) && dp[i - 1][j]) { dp[i][j] = true; } if(c == s2.charAt(j - 1) && dp[i][j - 1]) { dp[i][j] = true; } } } return dp[s1.length()][s2.length()]; } }
Reference: http://blog.csdn.net/u011095253/article/details/9248073
Solution2: 1D dp
思路和soluton1一样,动态规划的递推式为:
res[i][j] = res[i-1][j]&&s1.charAt(i-1)==s3.charAt(i+j-1) || res[i][j-1]&&s2.charAt(j-1)==s3.charAt(i+j-1)
可以看出递推式中只需要用到上一行的信息,所以我们只需要一个一维数组就可以完成历史信息的维护,为了更加优化,把短的字符串放在内层循环,这样就可以只需要短字符串的长度即可,所以空间复杂度是O(min(m,n))。时间复杂度还是O(m*n)。
Solution2: 1D dp
思路和soluton1一样,动态规划的递推式为:
res[i][j] = res[i-1][j]&&s1.charAt(i-1)==s3.charAt(i+j-1) || res[i][j-1]&&s2.charAt(j-1)==s3.charAt(i+j-1)
可以看出递推式中只需要用到上一行的信息,所以我们只需要一个一维数组就可以完成历史信息的维护,为了更加优化,把短的字符串放在内层循环,这样就可以只需要短字符串的长度即可,所以空间复杂度是O(min(m,n))。时间复杂度还是O(m*n)。
public class Solution { public boolean isInterleave(String s1, String s2, String s3) { if(s1 == null || s2 == null || s3 == null) return false; if(s1.length() + s2.length() != s3.length()) return false; String minStr = ""; String maxStr = ""; if(s1.length() > s2.length()) { minStr = s2; maxStr = s1; }else { minStr = s1; maxStr = s2; } boolean[] dp = new boolean[minStr.length() + 1]; dp[0] = true; for(int i = 1; i <= minStr.length(); i++) { if(minStr.charAt(i - 1) == s3.charAt(i - 1) && dp[i - 1]) { dp[i] = true; } } for(int i = 1; i <= maxStr.length(); i++) { dp[0] = dp[0] && maxStr.charAt(i - 1) == s3.charAt(i - 1); for(int j = 1; j <= minStr.length(); j++) { dp[j] = dp[j] && maxStr.charAt(i - 1) == s3.charAt(i + j - 1) || dp[j - 1] && minStr.charAt(j - 1) == s3.charAt(i + j - 1); } } return dp[minStr.length()]; } }Reference: http://blog.csdn.net/linhuanmars/article/details/24683159
No comments:
Post a Comment