LeetCode 97 交错字符串

题目:

给定三个字符串 s1s2s3, 验证 s3 是否是由 s1 和 s2 交错组成的。

输入输出:

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

分析:

首先可以分析一下这道题的解空间,比较容易想到的是对于s3中的每个字符我们需要考虑的是用s1或者s2中的字符去代替,这样的话它的解空间应该是o(2^n)的,我们就能想到暴力的解法,再加上一些判断。下面是暴力解法的代码:

class Solution {
public:
    bool fb(string s1, string s2, string s3, int a, int b, int c){
        if(c == s3.size()){
            return true;
        }
        if(a < s1.size() && b < s2.size() && s1[a] == s3[c] && s2[b] == s3[c]){
            return fb(s1, s2, s3, a + 1, b, c + 1) || fb(s1, s2, s3, a, b + 1, c + 1);
        }
        if(a < s1.size() && s1[a] == s3[c]){
            return fb(s1, s2, s3, a + 1, b, c + 1);
        }
        if(b < s2.size() && s2[b] == s3[c]){
            return fb(s1, s2, s3, a, b + 1, c + 1);
        }
        return false;
    }
    bool isInterleave(string s1, string s2, string s3) {
        if(s1.size() + s2.size() != s3.size()){
            return false;
        }
        return fb(s1, s2, s3, 0, 0, 0);
    }
};

思路比较简单,对s1,s2,s3都设一个下标为a, b, c。就是对于s3中的每一个字符,如果s1和s2都和该字符一样则返回s1指针后移

和s2后移结果的或,如果其中一个相同,则返回该下标后移的结果,如果都不相同,则直接返回false。这样的话,它的时间复杂度是o(2^n)的,有点高,运行上面的代码内存会超,所以需要寻找其他的方法。

对于这种指数时间复杂的问题,通常都用动态规划的方法来降低时间复杂度,这个题也是一样的。用一个二维数组dp[i][j]来表示s1下标为i - 1, s2下标为j - 1 的时候能不能匹配当前的s3。那么状态转移方程为:

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,可能是通过i匹配得到的,也可能是通过j匹配得到的,所以就有上面的式子,动态规划其实就是通过一个数组来记录之前的状态从而减少搜索的时间。下面是代码:

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

动态规划的时间复杂度是o(n^2)的,思路也是比较清晰,这里的思路优点跟最长公共序列相似。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值