LeetCode 0097 - Interleaving String
# Hints
DP
滚动数组优化
# 题面
Difficulty | Time Complexity Limit | Extra-Memory Complexity Limit |
---|---|---|
Medium |
Given strings s1
, s2
, and s3
, find whether s3
is formed by an interleaving of s1
and s2
.
An interleaving of two strings s
and t
is a configuration where they are divided into non-empty substrings such that:
s = s1 + s2 + ... + sn
t = t1 + t2 + ... + tm
|n - m| <= 1
The interleaving is
s1 + t1 + s2 + t2 + s3 + t3 + ...
ort1 + s1 + t2 + s2 + t3 + s3 + ...
Note: a + b
is the concatenation of strings a
and b
.
Example 1:
Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
Output: true
Example 2:
Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
Output: false
Example 3:
Input: s1 = "", s2 = "", s3 = ""
Output: true
# 题意
给定三个字符串 s1
, s2
和 s3
,判断 s3
是否可由 s1
和 s2
按照题目所述的规则转化得到。
# 题解
为便于描述,设字符串的下标从 起,字符串 s1
和 s2
的长度分别为 和 。
考虑动态规划,设 表示 和 是否能转化为 。
状态转移方程:
$\begin{cases} dp[0][0] &= 1\ dp[i][0] &= dp[i - 1][0]\ &\ (s_1[i] == s_3[i])\ dp[0][j] &= dp[0][j - 1]\ &\ (s_2[j] == s_3[j])\ dp[i][j] &= (dp[i - 1][j]\ &\ (s_1[i] == s_3[i + j])) \mid (dp[i][j - 1]\ & \ (s_2[j] == s_3[i + j])) \end{cases}$
答案即为 。时间复杂度为 。
然而这使用了 的额外空间,题目要求只能使用 的额外空间,使用滚动数组优化即可。
细节问题:
- 注意特判 的情况。
# AC代码
class Solution {
public:
bool isInterleave(const string & s1, const string & s2, const string & s3) {
// 特判
if (s1.length() + s2.length() != s3.length()) {
return false;
}
// 初始化
int n = s1.length(), m = s2.length();
bool dp[n + 1][m + 1];
memset(dp, false, sizeof(dp));
// 递推
dp[0][0] = true;
for (int i = 1; i <= n; i ++) {
dp[i][0] = dp[i - 1][0] && (s1[i - 1] == s3[i - 1]);
}
for (int j = 1; j <= m; j ++) {
dp[0][j] = dp[0][j - 1] && (s2[j - 1] == s3[j - 1]);
}
for (int i = 1; i <= n; i ++) for (int j = 1; j <= m; j ++) {
dp[i][j] = false;
dp[i][j] |= (dp[i - 1][j] && (s1[i - 1] == s3[i + j - 1]));
dp[i][j] |= (dp[i][j - 1] && (s2[j - 1] == s3[i + j - 1]));
}
// 返回
return dp[n][m];
}
};
# AC代码(滚动数组)
class Solution {
public:
bool isInterleave(const string & s1, const string & s2, const string & s3) {
// 特判
if (s1.length() + s2.length() != s3.length()) {
return false;
}
// 初始化
int n = s1.length(), m = s2.length();
bool dp[m + 1];
memset(dp, false, sizeof(dp));
// 递推
dp[0] = true;
for (int j = 1; j <= m; j ++) {
dp[j] = dp[j - 1] && (s2[j - 1] == s3[j - 1]);
}
for (int i = 1; i <= n; i ++) {
dp[0] &= (s1[i - 1] == s3[i - 1]);
for (int j = 1; j <= m; j ++) {
dp[j] &= (s1[i - 1] == s3[i + j - 1]);
dp[j] |= (dp[j - 1] && (s2[j - 1] == s3[i + j - 1]));
}
}
// 返回
return dp[m];
}
};
- 01
- Reading Papers - Kernel Concurrency06-01
- 02
- Linux Kernel - Source Code Overview05-01
- 03
- Linux Kernel - Per-CPU Storage05-01