97. 交错字符串

1.题目描述

给定三个字符串 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:
在这里插入图片描述
示例 2:
在这里插入图片描述
示例 3:
在这里插入图片描述
提示:
0 <= s1.length, s2.length <= 100
0 <= s3.length <= 200
s1、s2、和 s3 都由小写英文字母组成

2.思路

dp[i][j]表示s1的前i个字符和s2的前j个字符能否构成s3的前i+j个字符,dp[0][0]一定为true。
1.初始化 s1,s2,s3 的长度分别为 len1,len2,len3
2.若 len1+len2!=len3,表示一定不能构成交错字符串,返回 False
3.初始化 dp 为 (len1+1)∗(len2+1) 的 False 数组。
4.初始化第一列 dp[i][0],遍历第一列,遍历区间 [1,len1+1):
dp[i][0]=dp[i−1][0] && s1[i−1]==s3[i−1]。表示 s1的前 i 位是否能构成 s3 的前 i 位。因此需要满足的条件为,前 i-1 位可以构成 s3 的前 i-1 位且 s1 的第 i 位(s1[i-1])等于 s3 的第 i 位(s3[i-1])。
5.初始化第一行 dp[0][j],遍历第一行,遍历区间 [1,len2+1):
dp[0][j]=dp[0][j-1] && s2[j−1]==s3[j−1]。表示s2的前 j 位是否能构成 s3 的前 j 位。因此需要满足的条件为,s2 的前 j-1 位可以构成 s3 的前 j-1 位且 s2 的第 j 位(s2[j-1])等于 s3 的第 j 位(s3[j-1])。
遍历 dp 数组,每一行 i,遍历区间 [1,len1+1):
每一列 j,遍历区间 [1,len2+1):
  dp[i][j]=(dp[i][j-1] && s2[j-1]==s3[i+j-1]) || (dp[i-1][j] && s1[i-1]==s3[i+j-1]) 。解释:s1 前 i 位和 s2 的前 j 位能否组成 s3 的前 i+j 位取决于两种情况:
s1 的前 i 个字符和 s2 的前 j-1 个字符能否构成 s3 的前 i+j-1 位,且 s2 的第 j 位(s2[j-1])是否等于 s3 的第 i+j 位(s3[i+j-1])。
7.返回 dp[-1][-1]

3.代码

class Solution {
public:
    bool isInterleave(string s1, string s2, string s3) {
        int len1 = s1.size();
        int len2 = s2.size();
        int len3 = s3.size();
        if(len1 + len2 != len3){
            return false;
        }
        vector<vector<bool>> dp(len1 + 1, vector<bool>(len2 + 1));
        dp[0][0] = true;
        for(int i = 1; i <= len1; ++i){
            dp[i][0] = dp[i - 1][0] && s1[i - 1] == s3[i - 1];
        }
        for(int j = 1; j <= len2; ++j){
            dp[0][j] = dp[0][j - 1] && s2[j - 1] == s3[j - 1];
        }

        for(int i = 1;i <= len1;++i){
            for(int j = 1;j <= len2;++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[len1][len2];
    }
};

4.复杂度分析

时间复杂度:O(mn),m,n为s1,s2的长度
空间复杂度:O(mn)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一道比较有意思的字符串题目,我们可以使用动态规划来解决。使用 Kotlin 语言来实现,具体思路如下: 定义一个二维布尔数组 `dp[i][j]`,表示 s1 的前 i 个字符和 s2 的前 j 个字符能否交错组成 s3 的前 i+j 个字符。 初始状态:当 s1 和 s2 都为空时,s3 也为空,因此 `dp[0][0] = true`。 状态转移:对于每个 `dp[i][j]`,我们有两种选择: - 如果 `s1[i-1] == s3[i+j-1]`,则可以使用 `s1[i-1]` 来匹配 `s3[i+j-1]`,此时需要判断 `dp[i-1][j]` 是否为 true。 - 如果 `s2[j-1] == s3[i+j-1]`,则可以使用 `s2[j-1]` 来匹配 `s3[i+j-1]`,此时需要判断 `dp[i][j-1]` 是否为 true。 最终的结果为 `dp[s1.length][s2.length]`。 完整的代码如下: ```kotlin fun isInterleave(s1: String, s2: String, s3: String): Boolean { if (s1.length + s2.length != s3.length) { return false } val dp = Array(s1.length + 1) { BooleanArray(s2.length + 1) } // 初始化状态 dp[0][0] = true // 初始化第一行 for (j in 1..s2.length) { dp[0][j] = dp[0][j-1] && s2[j-1] == s3[j-1] } // 初始化第一列 for (i in 1..s1.length) { dp[i][0] = dp[i-1][0] && s1[i-1] == s3[i-1] } // 状态转移 for (i in 1..s1.length) { for (j in 1..s2.length) { 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] } ``` 我们可以使用以下代码测试这个函数: ```kotlin fun main() { val s1 = "aabcc" val s2 = "dbbca" val s3 = "aadbbcbcac" val res = isInterleave(s1, s2, s3) println(res) } ``` 输出结果为: ``` true ``` 这说明我们的代码已经正确地判断了 s3 是否是由 s1 和 s2 交错组成的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值