• 97 交错字符串


    题目

    给定三个字符串 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

    • 方法一:二维动态规划
    class Solution {
    public:
        bool isInterleave(string s1, string s2, string s3) {
        	//交错字符串,则s3全部是由s1和s2组成的,故他们的字符数一定是相等的,不相等则返回false
            if(s1.length()+s2.length()!=s3.length()) return false;
            //dp[i][j]表示s3的前i+j个元素,是否由s1的前i个元素和s2的前j个元素组成
            //i的取值范围是0~n,可以是前0个元素或前n个元素,故数组的行有n+1行
            vector<vector<bool>> dp(s1.length()+1,vector<bool>(s2.length()+1,false));
            
            dp[0][0]=true;//初始化前s3的0个元素匹配s1或s2,为true
            //初始化第一列,s3全是由s1匹配的。如果当前第i个元素匹配成功的话,看前i-1个元素是否匹配成功
            for(int i=1;i<=s1.size();i++)
                dp[i][0]= s3[i-1]==s1[i-1]&&dp[i-1][0];
            //初始化第一行,s3全是由s2匹配的。如果当前第j个元素匹配成功的话,看前j-1个元素是否匹配成功
            for(int j=1;j<=s2.size();j++)
                dp[0][j]= s3[j-1]==s2[j-1]&&dp[0][j-1];
            //dp[i][j]=(s1[i-1]==s3[i+j-1]&&dp[i-1][j])||(s2[j-1]==s3[i+j-1]&&dp[i][j-1])
            //或 表示当前第i+j-1个元素既可以匹配s1的第i个元素也可以匹配s2的第j个元素,二者满足一种情况即可
            for(int i=1;i<=s1.size();i++)
            {
                for(int j=1;j<=s2.size();j++)
                    dp[i][j]= (s1[i-1]==s3[i+j-1]&&dp[i-1][j])||(s2[j-1]==s3[i+j-1]&&dp[i][j-1]);
            }
            return dp[s1.size()][s2.size()];//返回是否匹配了s1的前m个元素s2的前n个元素
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 时间复杂度O(n^2)

    • 空间复杂度O(n^2)

    • 思路

      • 交错字符串,s3全部是由s1和s2的所有字符组成的
      • dp[i][j]表示s3的前i+j个字符,是否由s1的前i个字符和s2的前j个字符组成。先初始化dp数组的边界,再根据递推公式填dp数组
      • 递推公式:dp[i][j]= (s1[i-1]==s3[i+j-1]&&dp[i-1][j])||(s2[j-1]==s3[i+j-1]&&dp[i][j-1])
      • 详细解释在代码注释
    • 法二:滚动数组实现一维动态规划

    class Solution {
    public:
        bool isInterleave(string s1, string s2, string s3) {
        	//如果s3的字符数不等于s1和s2的字符数之和,返回false
            if(s1.length()+s2.length()!=s3.length()) return false;
      		//一维dp数组
            vector<bool> f(s2.size()+1,false);
            f[0]=true;//初始化边界为true,s3的前0个字符与s1或s2匹配成功
    		//初始化对应到二维dp中就是第一行,即s3全部匹配的是s2的字符
            for(int i=1;i<=s2.size();i++)
                f[i]=s2[i-1]==s3[i-1]&&f[i-1];
            //两层for循环,外层for对应二维数组中的列,内层for表示一行
            for(int i=1;i<=s1.size();i++)
            {
            	//先初始化当前行的第一个元素,判断s3的第i个元素是否和s1的第1个元素匹配,且s3的前i-1个元素是否匹配成功
            	//对应在二维数组中就是第一列的元素,即s3全部和s1进行匹配
                f[0]=s1[i-1]==s3[i-1]&&f[0];
                //填当前行的dp数组
                //当前位置的元素是否匹配成功只与它左边的元素和上边的元素有关
                //如果s3的第i+j个元素和s1的第i个元素匹配成功,则要判断s3是否已经把s1的前i-1个元素已经匹配完了,在一维数组中表示为尚未被改次循环修改的f[j]的值
                //如果s3的第i+j个元素和s2的第j个元素匹配成功,则要判断s3是否已经把s2的前j-1个元素已经匹配完了,在一维数组中表示为f[j-1]
                //s3的第i+j个字符只要成功匹配一个字符即可,故两种情况用 或 连接
                for(int j=1;j<=s2.size();j++)
                    f[j]=(s1[i-1]==s3[i+j-1]&&f[j])||(s2[j-1]==s3[i+j-1]&&f[j-1]);
            }
    
            return f[s2.size()];
        }
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 时间复杂度O(n^2)
    • 空间复杂度O(n)
    • 思路
      • 由于二维动态规划中,确定当前行的值时只用到当前行和上一行的值,且最后只需要最后一行最后一个元素的值,故可以采用滚动数组将其优化为一维动态规划
      • 详细解释见代码注释
  • 相关阅读:
    C#快速入门
    JavaScript高级,ES6 笔记 第一天
    使用JS简单实现一下apply、call和bind方法
    Websocket
    House of orange
    Java 实现RSA 加解密算法 公钥加密传参
    StrictMode卡顿与泄漏检测-StrictMode原理(2)
    全栈开发之基于云开发实现微信聊天功能
    单调栈leetcode.907
    Kaggle 专利匹配比赛赛后总结
  • 原文地址:https://blog.csdn.net/weixin_45781228/article/details/126399594