leetcode97. 交错字符串
给定三个字符串 s1、s2、s3,请你帮忙验证 s3 是否是由 s1 和 s2 交错 组成的。
两个字符串 s 和 t 交错 的定义与过程如下,其中每个字符串都会被分割成若干 非空
子字符串:
s = s1 + s2 + … + sn
t = t1 + t2 + … + tm
|n - m| <= 1
交错 是 s1 + t1 + s2 + t2 + s3 + t3 + … 或者 t1 + s1 + t2 + s2 + t3 + s3 + …
注意:a + b 意味着字符串 a 和 b 连接。
示例 1:
输入:s1 = “aabcc”, s2 = “dbbca”, s3 = “aadbbcbcac”
输出:true
示例 2:
输入:s1 = “aabcc”, s2 = “dbbca”, s3 = “aadbbbaccc”
输出:false
示例 3:
输入:s1 = “”, s2 = “”, s3 = “”
输出:true
提示:
0 <= s1.length, s2.length <= 100
0 <= s3.length <= 200
s1、s2、和 s3 都由小写英文字母组成
题目分析
- 问题定义:判断字符串
s3
是否可以通过将字符串s1
和s2
交错拼接而成。 - 关键概念:通过动态规划构建一个二维数组
dp
,其中dp[i][j]
表示s3
的前i+j
个字符能否由s1
的前i
个字符和s2
的前j
个字符组成。
算法介绍
- 动态规划:使用二维数组
dp
来存储中间结果,以优化时间复杂度。
算法步骤
- 初始化动态规划数组
dp
,大小为(n+1) x (m+1)
,其中n
和m
分别是s1
和s2
的长度。 - 设置边界条件:
dp[0][0] = true
,表示空字符串可以由空字符串交错而成。 - 遍历
dp
数组,从第一行和第一列开始:- 如果
i > 0
且s3[i+j-1] == s1[i-1]
,则dp[i][j] |= dp[i-1][j]
。 - 如果
j > 0
且s3[i+j-1] == s2[j-1]
,则dp[i][j] |= dp[i][j-1]
。
- 如果
- 返回
dp[n][m]
,即s3
是否可以通过s1
和s2
交错拼接而成。
算法流程
算法代码
//dp[i][j]表示s3的第i+j个字符能否被s1的前i个字符和s2的前j个字符组成
//s3[i+j-1]==s1[i-1] dp[i][j]|=(dp[i-1][j])
//s3[i+j-1]==s2[j-1] dp[i][j]|=(dp[i][j-1])
class Solution {
public:
bool isInterleave(string s1, string s2, string s3) {
int n=s1.size();
int m=s2.size();
if(n+m!=s3.size()) return false;
vector<vector<int>> dp(n+1,vector<int>(m+1,false));
dp[0][0]=true;
for(int i=0;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
if(i>0 && s3[i+j-1]==s1[i-1])
{
dp[i][j]|=(dp[i-1][j]);
}
if(j>0 && s3[i+j-1]==s2[j-1])
{
dp[i][j]|=(dp[i][j-1]);
}
}
}
return dp[n][m];
}
};
算法分析
- 时间复杂度:O(n*m),其中n和m分别是
s1
和s2
的长度。 - 空间复杂度:O(n*m),用于存储动态规划数组。
- 易错点:正确处理字符串匹配和动态规划数组的更新。
相似题目
题目 | 链接 |
---|---|
97. 交错字符串 | LeetCode |
1143. 最长公共子序列 | LeetCode |
300. 最长递增子序列 | LeetCode |