97. Interleaving String
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.
Example 1:
Input: s1 = “aabcc”, s2 = “dbbca”, s3 = “aadbbcbcac”
Output: true
Example 2:
Input: s1 = “aabcc”, s2 = “dbbca”, s3 = “aadbbbaccc”
Output: false
方法1: dynamic programming
Tushar: https://www.youtube.com/watch?v=ih2OZ9-M3OM
用dp的方法,用s1[i - 1]和s2[j - 1]位置截断的字串能否interleave出s3[i + j - 1]。首先判断当前位置是否和s1[i - 1]或s2[j - 1]中的某一个相等。这是因为如果为true的话,s3的末位字符必然来自其一。假设s1[i - 1] 和对应位的s3相等,我们要判断除去s1[i -1]和s3的当前位,前面是否能interleave;如果s2[j - 1] 和对应位的s3相等,要判断除去s2[j - 1]和s3当前位,是否能interleave。两次机会可以将dp[i][j] = 1,update时是相或的关系。
vector<vector<\int>> dp(m + 1, vector<\int> (n + 1, 0)) : 用s1[i - 1]和s2[j - 1]位置截断的字串能否interleave出s3[i + j - 1]。
initialize: dp[0][0] = 1,空字符可以interleave出空字符。第一行与第一列的intialization可以放进大循环里。
transfer:
if (s1[i - 1] == s3[i + j - 1]) {
dp[i][j] |= dp[i - 1][j];
}
if (s2[j - 1] == s3[i + j - 1]) {
dp[i][j] |= dp[i][j - 1];
}。
return: dp[0][0]。
易错点:
- 与s3比较时,s3的坐标为 i + j + 1, 比如 i = 1, j = 1, 我们尝试将s1[0] 与s3[1] 比较, 而不是s3[0],因为此时默认s2[0]必须被包括。
- 初始化dp[0][0]这个点。
- dp 是 bool的话,必须用 || 相或,用 int的话,0/1可以用 |= 的运算符。
Complexity
Time complexity: O(mn)
Space complexity: O(mn)
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
int m = s1.size(), n = s2.size(), l = s3.size();
if (m + n != l) return false;
vector<vector<int>> dp(m + 1, vector<int> (n + 1, 0));
// init
dp[0][0] = 1;
// first column
for (int i = 0; i < m; i++) {
if (s1[i] == s3[i]) dp[i + 1][0] = 1;
else break;
}
// first row
for (int j = 0; j < n; j++) {
if (s2[j] == s3[j]) dp[0][j + 1] = 1;
else break;
}
for (int i = 1; i < m + 1; i++) {
for (int j = 1; j < n + 1; j++) {
if (s1[i - 1] == s3[i + j - 1]) {
dp[i][j] |= dp[i - 1][j];
}
if (s2[j - 1] == s3[i + j - 1]) {
dp[i][j] |= dp[i][j - 1];
}
}
}
return dp.back().back();
}
};
降维没写好,bug:
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
int m = s1.size(), n = s2.size(), l = s3.size();
if (m + n != l) return false;
vector<int> dp(n + 1, 0);
for (int j = 1; j < n + 1; j++) {
if (s2[j - 1] == s3[j - 1]) dp[j] = 1;
else break;
}
for (int i = 1; i < m + 1; i++) {
for (int j = n; j >= 1; j--) {
if (s1[i - 1] != s3[i + j - 1]) dp[j] = 0;
if (s2[j - 1] == s3[i + j - 1]) dp[j] |= dp[j - 1];
}
}
return dp.back();
}
};
方法2: recursion with memoization
官方题解:https://leetcode.com/problems/interleaving-string/solution/