97. 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: dynamic programming

Tushar: https://www.youtube.com/watch?v=ih2OZ9-M3OM

用dp的方法,用s1[i - 1]和s2[j - 1]位置截断的字串能否interleave出s3[i + j - 1]。首先判断当前位置是否和s1[i - 1]或s2[j - 1]中的某一个相等。这是因为如果为true的话,s3的末位字符必然来自其一。假设s1[i - 1] 和对应位的s3相等,我们要判断除去s1[i -1]和s3的当前位,前面是否能interleave;如果s2[j - 1] 和对应位的s3相等,要判断除去s2[j - 1]和s3当前位,是否能interleave。两次机会可以将dp[i][j] = 1,update时是相或的关系。

vector<vector<\int>> dp(m + 1, vector<\int> (n + 1, 0)) : 用s1[i - 1]和s2[j - 1]位置截断的字串能否interleave出s3[i + j - 1]。
initialize: dp[0][0] = 1,空字符可以interleave出空字符。第一行与第一列的intialization可以放进大循环里。
transfer:
if (s1[i - 1] == s3[i + j - 1]) {
dp[i][j] |= dp[i - 1][j];
}
if (s2[j - 1] == s3[i + j - 1]) {
dp[i][j] |= dp[i][j - 1];
}。
return: dp[0][0]。

易错点:

  1. 与s3比较时,s3的坐标为 i + j + 1, 比如 i = 1, j = 1, 我们尝试将s1[0] 与s3[1] 比较, 而不是s3[0],因为此时默认s2[0]必须被包括。
  2. 初始化dp[0][0]这个点。
  3. dp 是 bool的话,必须用 || 相或,用 int的话,0/1可以用 |= 的运算符。

Complexity

Time complexity: O(mn)
Space complexity: O(mn)

class Solution {
public:
    bool isInterleave(string s1, string s2, string s3) {
        int m = s1.size(), n = s2.size(), l = s3.size();
        if (m + n != l) return false;
        vector<vector<int>> dp(m + 1, vector<int> (n + 1, 0));
        // init
        dp[0][0] = 1;
        // first column
        for (int i = 0; i < m; i++) {
            if (s1[i] == s3[i]) dp[i + 1][0] = 1;
            else break;
        }
        // first row
        for (int j = 0; j < n; j++) {
            if (s2[j] == s3[j]) dp[0][j + 1] = 1;
            else break;
        }
        for (int i = 1; i < m + 1; i++) {
            for (int j = 1; j < n + 1; j++) {
                if (s1[i - 1] == s3[i + j - 1]) {
                    dp[i][j] |= dp[i - 1][j];
                }
                if (s2[j - 1] == s3[i + j - 1]) {
                    dp[i][j] |= dp[i][j - 1];
                }
            }
        }
        return dp.back().back();
    }
};

降维没写好,bug:

class Solution {
public:
    bool isInterleave(string s1, string s2, string s3) {
        int m = s1.size(), n = s2.size(), l = s3.size();
        if (m + n != l) return false;
        vector<int> dp(n + 1, 0);
        for (int j = 1; j < n + 1; j++) {
            if (s2[j - 1] == s3[j - 1]) dp[j] = 1;
            else break;
        }
        
        for (int i = 1; i < m + 1; i++) {
            for (int j = n; j >= 1; j--) {
                
                if (s1[i - 1] != s3[i + j - 1]) dp[j] = 0;
                if (s2[j - 1] == s3[i + j - 1]) dp[j] |= dp[j - 1];
            }
        }
        return dp.back();
    }
};

方法2: recursion with memoization

官方题解:https://leetcode.com/problems/interleaving-string/solution/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值