[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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章