[leetcode] 97. Interleaving String

Interleaving String

Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.

Example 1:

Input: s1 = “aabcc”, s2 = “dbbca”, s3 = “aadbbcbcac”
Output: true

Example 2:

Input: s1 = “aabcc”, s2 = “dbbca”, s3 = “aadbbbaccc”
Output: false

解法1:动态规划

构造一个二维数组,dp[i][j]表示字符串到位置i和字符串s2到位置j能组成s3
dp[0][0]=1;
当i=0时,dp[i][j] = dp[i][j-1] && s2[j-1] == s3[j-1];
当j=0时,dp[i][j] = dp[i-1][j] && s1[i-1] == s3[i-1];
否则: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]);

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

解法2:DFS

使用一个hashmap来记录匹配失败的情况,存的值为key=i*s3.size()+j来表示一对(i,j);
i表示s1当前的位置,j表示s2当前的位置。
当i=s1.size;判断s2剩余的部分和s3剩余部分是否相等;
当j=s2.size;判断s1剩余的部分和s3剩余部分是否相等;
否则,如果s1[i]==s3[k] 调用递归函数helper(s1,i+1,s2,j,s3,k+1,s))
或者s2[j]==s3[k],helper(s1,i,s2,j+1,s3,k+1, s)
把匹配失败的key加入到hashmap中。

class Solution {
public:
    bool isInterleave(string s1, string s2, string s3) {
        if(s1.size()+s2.size() != s3.size()) return false;
        unordered_set<int> s;
        return helper(s1, 0, s2, 0, s3, 0, s);
    }
    
    bool helper(string s1, int i, string s2, int j, string s3,int k, unordered_set<int>& s){
        int key = i * s3.size() + j;
        if (s.count(key)) return false;
        if(i==s1.size()) return s2.substr(j) == s3.substr(k);
        if(j==s2.size()) return s1.substr(i) == s3.substr(k);
        if((s1[i]==s3[k] && helper(s1,i+1,s2,j,s3,k+1,s)) || (s2[j]==s3[k] && helper(s1,i,s2,j+1,s3,k+1, s)))
            return true;
        s.insert(key);
        return false;
    }
};

解法3:BFS

用一个队列来辅助BFS,循环 queue 中元素个数的次数,在 for 循环中,对队首元素进行解码,得到i和j值,
如果i小于 n1,说明 s1 还有剩余字符,如果 s1 当前字符等于 s3 当前字符,那么把 s1 的下一个位置 i+1 跟j一起加码算出 key 值,如果该 key 值不在于集合中,则加入集合,同时加入队列 queue 中;
同理,如果j小于 n2,说明 s2 还有剩余字符,如果 s2 当前字符等于 s3 当前字符,那么把 s2 的下一个位置 j+1 跟i一起加码算出 key 值,如果该 key 值不在于集合中,则加入集合,同时加入队列 queue 中。
for 循环结束后,k自增1。最后如果匹配成功的话,那么 queue 中应该只有一个 (n1, n2) 的 key 值,且k此时等于 n3,所以当 queue 为空或者k不等于 n3 的时候都要返回 false,

class Solution {
public:
    bool isInterleave(string s1, string s2, string s3) {
        if(s1.size()+s2.size() != s3.size()) return false;
        int n1=s1.size(),n2=s2.size(),n3=s3.size();
        unordered_set<int> s;
        queue<int> q;
        q.push(0);
        int i=0,j=0,k=0;
        while(!q.empty() && k<n3){
            int len = q.size();
            for(int t=0;t<len;t++){
                i = q.front() / n3;
                j = q.front() % n3; 
                q.pop();
                if (i < n1 && s1[i] == s3[k]) {
                    int key = (i + 1) * n3 + j;
                    if (!s.count(key)) {
                        s.insert(key);
                        q.push(key);
                    }
                }
                if (j < n2 && s2[j] == s3[k]) {
                    int key = i * n3 + j + 1;
                    if (!s.count(key)) {
                        s.insert(key);
                        q.push(key);
                    }
                }
            }
            k++;
        }
        return !q.empty() && k == n3;
    }
};

参考

https://www.cnblogs.com/grandyang/p/4298664.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值