[抄题]:
给出三个字符串:s1、s2、s3,判断s3是否由s1和s2交叉构成。(洗牌)
比如 s1 = "aabcc" s2 = "dbbca"
- 当 s3 = "aadbbcbcac",返回 true.
- 当 s3 = "aadbbbaccc", 返回 false.
[思维问题]:
- 不知道怎么表示交叉。分析要用三维数组,i j k。但是分析j 是否等于i+j,就只用二维数组了。
- 不知道为什么看最后一位:第一位不知道是谁出的,但是最后一位非此即彼,可以用来递推。
- 不知道状态函数和判断字符函数的关系:二者是要分开的。
[一句话思路]:
[输入量]:空: 正常情况:特大:特小:程序里处理到的特殊情况:异常情况(不合法不合理的输入):
[画图]:
[一刷]:
- 行列初始化的规则和普通递归的规则一样,状态函数和判断字符函数都有且分开。
- 序列dp。第0位初始化,i = 1,i<=n时操作。因此,f[0][0]也要初始化
- dp中的数组长度一般直接写s1.length(),不用新取
[二刷]:
[三刷]:
[四刷]:
[五刷]:
[五分钟肉眼debug的结果]:
[总结]:
行列初始化的规则和普通递归的规则一样,状态函数和判断字符函数都有且分开。
[复杂度]:Time complexity: O(n^2) Space complexity: O(n^2)
[英文数据结构或算法,为什么不用别的数据结构或算法]:
[其他解法]:
[Follow Up]:
[LC给出的题目变变变]:
343. Integer Break 最值dp
646. Maximum Length of Pair Chain 最值dp
[代码风格] :
else if 又是热脸贴冷屁股
public class Solution { /* * @param s1: A string * @param s2: A string * @param s3: A string * @return: Determine whether s3 is formed by interleaving of s1 and s2 */ public boolean isInterleave(String s1, String s2, String s3) { //corner case if (s1.length() + s2.length() != s3.length()) { return false; } //state boolean[][] interleaved = new boolean[s1.length() + 1][s2.length() + 1]; interleaved[0][0] = true; //initialization //s1 == 0 for (int i = 1; i <= s2.length(); i++) { if (s2.charAt(i - 1) == s3.charAt(i - 1) && interleaved[0][i - 1]) {//i -1 && interleaved[0][i] = true; } } //s2 == 0 for (int j = 1; j <= s1.length(); j++) { if (s1.charAt(j - 1) == s3.charAt(j - 1)&& interleaved[j - 1][0]) {// interleaved[j][0] = true; } } //function for (int i = 1; i <= s1.length(); i++) { for (int j = 1; j <= s2.length(); j++) { if (s1.charAt(i - 1) == s3.charAt(i + j - 1) && interleaved[i - 1][j]) { interleaved[i][j] = true; }else if (s2.charAt(j - 1) == s3.charAt(i + j - 1) && interleaved[i][j - 1]) { interleaved[i][j] = true; }else { interleaved[i][j] = false; } } } //answer return interleaved[s1.length()][s2.length()]; } }