97.交错字符串
标签: dynamic-programming
, string
难度: Medium
通过率: 41.02%
原题链接: https://leetcode.com/problems/interleaving-string/description/
题目描述
给定字符串 , 和 ,判断 是否由 和 的交错组成。
字符串 和 的交错是一种配置,其中 和 被分割成分别的 和 个子串,如下所示:
交错方式为 或 。
注意: 表示字符串 和 的拼接。
解题思路
这是一个经典的动态规划问题。设一个二维布尔数组 表示字符串 的前 个字符是否由 的前 个字符和 的前 个字符交错组成。我们需要确定 。主要思想如下:
-
如果 且 为真,那么 为真,这意味着可以通过将 的前 个字符与 的前 个字符加上 第 个字符来构成 的前 个字符。
-
如果 且 为真,那么 为真,这意味着可以通过将 的前 个字符与 的前 个字符加上 的第 个字符来构成 的前 个字符。
初始条件为 ,因为空串之间是互相交错的。
最终结果取决于 的值。
代码实现
- Python
- C++
- JavaScript
- Java
def isInterleave(s1, s2, s3):
# 如果长度不匹配,直接返回 False
if len(s1) + len(s2) != len(s3):
return False
# 初始化 DP 数组
dp = [[False] * (len(s2) + 1) for _ in range(len(s1) + 1)]
# 空串之间肯定是交错的
dp[0][0] = True
# 处理 s1 边界情况
for i in range(1, len(s1) + 1):
dp[i][0] = dp[i - 1][0] and s1[i - 1] == s3[i - 1]
# 处理 s2 边界情况
for j in range(1, len(s2) + 1):
dp[0][j] = dp[0][j - 1] and s2[j - 1] == s3[j - 1]
# 填充 DP 表
for i in range(1, len(s1) + 1):
for j in range(1, len(s2) + 1):
dp[i][j] = (dp[i - 1][j] and s1[i - 1] == s3[i + j - 1]) or (dp[i][j - 1] and s2[j - 1] == s3[i + j - 1])
return dp[-1][-1]
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
if (s1.length() + s2.length() != s3.length()) {
return false;
}
vector<vector<bool>> dp(s1.length() + 1, vector<bool>(s2.length() + 1, false));
dp[0][0] = true;
for (int i = 1; i <= s1.length(); ++i) {
dp[i][0] = dp[i - 1][0] && s1[i - 1] == s3[i - 1];
}
for (int j = 1; j <= s2.length(); ++j) {
dp[0][j] = dp[0][j - 1] && s2[j - 1] == s3[j - 1];
}
for (int i = 1; i <= s1.length(); ++i) {
for (int j = 1; j <= s2.length(); ++j) {
dp[i][j] = (dp[i - 1][j] && s1[i - 1] == s3[i + j - 1]) ||
(dp[i][j - 1] && s2[j - 1] == s3[i + j - 1]);
}
}
return dp[s1.length()][s2.length()];
}
};
function isInterleave(s1, s2, s3) {
if (s1.length + s2.length !== s3.length) {
return false;
}
const dp = Array(s1.length + 1).fill(null).map(() => Array(s2.length + 1).fill(false));
dp[0][0] = true;
for (let i = 1; i <= s1.length; ++i) {
dp[i][0] = dp[i - 1][0] && s1[i - 1] === s3[i - 1];
}
for (let j = 1; j <= s2.length; ++j) {
dp[0][j] = dp[0][j - 1] && s2[j - 1] === s3[j - 1];
}
for (let i = 1; i <= s1.length; ++i) {
for (let j = 1; j <= s2.length; ++j) {
dp[i][j] = (dp[i - 1][j] && s1[i - 1] === s3[i + j - 1]) ||
(dp[i][j - 1] && s2[j - 1] === s3[i + j - 1]);
}
}
return dp[s1.length][s2.length];
}
class Solution {
public boolean isInterleave(String s1, String s2, String s3) {
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) {
dp[i][0] = dp[i - 1][0] && s1.charAt(i - 1) == s3.charAt(i - 1);
}
for (int j = 1; j <= s2.length(); ++j) {
dp[0][j] = dp[0][j - 1] && s2.charAt(j - 1) == s3.charAt(j - 1);
}
for (int i = 1; i <= s1.length(); ++i) {
for (int j = 1; j <= s2.length(); ++j) {
dp[i][j] = (dp[i - 1][j] && s1.charAt(i - 1) == s3.charAt(i + j - 1)) ||
(dp[i][j - 1] && s2.charAt(j - 1) == s3.charAt(i + j - 1));
}
}
return dp[s1.length()][s2.length()];
}
}
复杂度分析
时间复杂度:,其中 和 分别是 和 的长度。我们需要填写一个 的 DP 表。 空间复杂度:,用于存储 DP 表。可以通过优化将其降低到 。