LeetCode 97题(字符串)

LeetCode:97 交叉字符串(东方财富0807—1)

题目描述:
给定三个字符串 s1, s2, s3, 验证 s3 是否是由 s1 和 s2 交错组成的。

示例 1:

输入: s1 = “aabcc”, s2 = “dbbca”, s3 = “aadbbcbcac”
输出: true

示例 2:

输入: s1 = “aabcc”, s2 = “dbbca”, s3 = “aadbbbaccc”
输出: false

解题思路:
为了实现这个算法, 我们将使用一个 2D 的布尔数组 dp 。dp[i][j] 表示用 s1 的前 (i+1)和 s2 的前 (j+1)个字符,总共 (i+j+2)个字符,是否交错构成 s3 的前缀。为了求出 dp[i][j],我们需要考虑 2 种情况:

  1. s1 的第 i 个字符 s2 的第 j个字符都不能匹配 s3 的第 k 个字符,其中 k=i+j+1 。这种情况下,s1 和 s2 的前缀无法交错形成s3 长度为 k+1 的前缀。因此,我们让 dp[i][j]为 False。
  2. s1 的第 i个字符或者 s2的第 j个字符可以匹配 s3 的第 k 个字符,其中 k=i+j+1。假设匹配的字符是 x且与 s1 的第 i 个字符匹配,我们就需要把 x 放在已经形成的交错字符串的最后一个位置。此时,为了我们必须确保 s1 的前 (i-1) 个字符和 s2 的前 j 个字符能形成 s3 的一个前缀。类似的,如果我们将 s2 的第 j个字符与 s3 的第 k 个字符匹配,我们需要确保 s1 的前 i 个字符和 s2的前 (j-1) 个字符能形成 s3 的一个前缀,我们就让 dp[i][j]为 True。

以下图为例,行数为s1.size()+1,列数为s2.size()+1,
在这里插入图片描述在这里插入图片描述
在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
判断上面的dp[i-1][j]是否为T,若是T,则左侧的s1[i-1]是否与s3[i+j-1]的值相同
在这里插入图片描述
同理,左侧的dp[i][j-1]是否为T,若是T,则上面的s2[j-1]是否与s3[i+j-1]的值相同
在这里插入图片描述
最终得到
在这里插入图片描述
复杂度分析

  • 时间复杂度:O(m⋅n) 。计算 dp 数组需要 m∗n 的时间。
  • 空间复杂度:O(m⋅n)。2 维的 dp 数组需要 (m+1)∗(n+1) 的空间。 m 和 n 分别是 s1 和 s2字符串的长度。

代码:

 bool isInterleave(string s1, string s2, string s3) {
        int n1 = s1.length();
        int n2 = s2.length();
        int n3 = s3.length();
        if(n3!=n1+n2) //s3长度与s1s2长度之和不等,则s3肯定不能由s1s2交错字符串构成
            return false;
        
        bool* flag = new bool[(n1+1)*(n2+1)];//记录dp
        memset(flag,0,(n1+1)*(n2+1));//初始化
        int cols = n2+1;
        
        for(int i=0;i<=n1;i++)
        {
            for(int j=0;j<=n2;j++)
            {
                if(i==0 &&j==0)//第0行第0列
                {
                    flag[i*cols+j]=true;
                }else if(i==0) //第0行第1-cols-1列
                {
                    flag[i*cols+j] = (flag[j-1]&&(s2[j-1]==s3[i+j-1]));//左边和上边
                }else if(j==0) //第1列第1到rows-1行
                {
                    flag[i*cols+j] = (flag[(i-1)*cols]&&(s1[i-1]==s3[i+j-1])); //上边和左边
                }else{  //第1-rows-1行第1-cols-1列
                    flag[i*cols+j] = (flag[(i-1)*cols+j] && s1[i-1] ==s3[i+j-1]) || (flag[i*cols+j-1] && s2[j-1] == s3[i+j-1]);//上边和左边||左边和上边
                }
                    
            }
        }
        return flag[n1*cols+n2];
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值