(Version 0.0)
Interleaving String这道题是一道典型的DP题目,思路就是最基本的利用前一个subproblem(substring)的解加上对当前char的判断来解决当前问题的典型的sequence DP问题。我们要考虑的一般性的子问题是:取s1.substring(i)和s2.substring(j),能否interleave成s3.substring(i + j)。如果s1.substring(i)和s2.substring(j)想要interleave成s3.substring(i + j),那么s1.substring(i)和s2.substring(j)中必有至少一个和s3.substring(i + j)有相同的最后一个char,所以易得状态转移关系:若取s1.charAt(i - 1)和s3.charAt(i + j - 1)匹配,则s1.substring(i - 1)和s2.substring(j)必须一起解决掉s3.substring(i + j - 1),即dp[i - 1][j] && s1.charAt(i - 1) == s3.charAt(i + j - 1);或者若去s2.charAt(j - 1)和s3.charAt(i + j - 1)匹配,则s1.substring(i)和s2.substring(j - 1)必须一起解决掉s3.substring(i + j - 1),即dp[i][j - 1] && s2.charAt(j - 1) == s3.charAt(i + j - 1)。代码如下:
1 public class Solution { 2 public boolean isInterleave(String s1, String s2, String s3) { 3 if (s1.length() + s2.length() != s3.length()) { 4 return false; 5 } 6 boolean[][] dp = new boolean[s1.length() + 1][s2.length() + 1]; 7 dp[0][0] = true; 8 for (int i = 1; i <= s2.length(); i++) { 9 if (dp[0][i - 1] && s3.charAt(i - 1) == s2.charAt(i - 1)) { 10 dp[0][i] = true; 11 } else { 12 break; 13 } 14 } 15 for (int i = 1; i <= s1.length(); i++) { 16 if (dp[i - 1][0] && s3.charAt(i - 1) == s1.charAt(i - 1)) { 17 dp[i][0] = true; 18 } else { 19 break; 20 } 21 } 22 for (int i = 1; i <= s1.length(); i++) { 23 for (int j = 1; j <= s2.length(); j++) { 24 char c = s3.charAt(i + j - 1); 25 dp[i][j] = dp[i][j - 1] && s2.charAt(j - 1) == c || dp[i - 1][j] && s1.charAt(i - 1) == c; 26 } 27 } 28 return dp[s1.length()][s2.length()]; 29 } 30 }
总体来说只要掌握了CLRS或者其他教科书上面的sequence DP的例子,就会发现这题其实换汤不换药,可以套用典型的DP模式。