力扣刷题笔记 97. 交错字符串 C#

7月18日签到题,题目如下:

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

 

示例 1:

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

输入:s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
输出:false

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/interleaving-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

首先想到双指针,即使用两个指针 index1 和 index2,分别用 s1[index1] 和 s2[index2] 与 s3[index1 + index2] 进行对比。如果对比过程中,s1[index1] 或 s2[index2] 与 s3[index1 + index2] 都不相等,那么直接返回 false,如果对比成功结束则返回 true。

以下为自己以双指针思路提交的错误代码,我多用了一个整型标记当前比对的 s3 的下标:

public class Solution {
    public bool IsInterleave(string s1, string s2, string s3) {
        int mainLast = s3.Length - 1;
        int last1 = s1.Length - 1;
        int last2 = s2.Length - 1;
        int mainKey = 0;
        int key1 = 0;
        int key2 = 0;
        while (mainKey <= mainLast && 
            key1 <= last1 && key2 <= last2)
        {
            if (s1[key1] == s3[mainKey])
            {
                key1++;
                mainKey++;
            }
            else if (s2[key2] == s3[mainKey])
            {
                key2++;
                mainKey++;
            }
            else
            {
                return false;
            }
        }
        return true;
    }
}

这种方法如何修改都会报错,因为可能出现 s1[index1] 和 s2[index2] 相同的时候,可能只有其中选取其中一个才能得到唯一解。此时双指针就没有办法判断哪一个选择能够到达唯一解。如 s1 = aabcc,s2 = dbbca,s3 = aadbbcbcac 这样的情况。

所以,这里还是使用动态规划。取一个长度为 (s1.Length + 1) * (s2.Length + 1)的二维 bool 数组 dp 保存状态。dp[i,j] 表示比较完 s1 前 i 个字符、 s2 前 j 个字符和 s3 前 i + j 个字符的结果。因为存在 s1 或者 s2 没有被比较过的状态,所以长度多取一位,表示该状态。判断dp[i][j] 时,状态会转移自 dp[i- 1][j] 或者 dp[i][j - 1],即前一状态是 比较完 s1 前 i - 1 个字符和 s2 前 j 个字符的结果,或者 比较完 s1 前 i 个字符和 s2 前 j - 1 个字符的结果。当转移自 dp[i - 1][j] 时,当前还需要判断一次 s1 的第 i 个字符和 s3 的第 i + j 个字符是否匹配,记作 s1[i - 1] == s3[i + j - 1]。转移自 dp[i][j - 1] 时则是 s2[j - 1] == s3[i + j - 1]。

当 i <= 0 时,状态只会转移自 dp[i][j-1]。当 j <= 0 时,状态只会转移自 dp[i -1][0]。

确定边界条件,就是 i = j = 0 时。此时 3 个字符串都为空,也满足题意,故 dp[0][0] = true。

复杂度分析:

遍历了一个长度为 (s1.Length + 1) * (s2.Length + 1)的二维数组,即时间复杂度为 O(M*N)。

建立了一个长度为 (s1.Length + 1) * (s2.Length + 1)的二维数组,即空间复杂度也为 O(M*N)。这里可以使用滚动数组优化空间复杂度到 O(N),这里不作讨论。

以下为自己提交的代码:

public class Solution {
    public bool IsInterleave(string s1, string s2, string s3) {
        if (s1.Length + s2.Length != s3.Length)
        {
            return false;
        }
        bool[,] dp = new bool[s1.Length + 1,s2.Length + 1];
        dp[0,0] = true;
        for (int i = 0;i < s1.Length + 1;i++)
        {
            for (int j = 0;j < s2.Length + 1;j++)
            {
                if (i > 0)
                {
                    dp[i,j] |= dp[i - 1,j] && s1[i - 1] == s3[i + j - 1];
                }
                if (j > 0)
                {
                    dp[i,j] |= dp[i,j - 1] && s2[j - 1] == s3[i + j - 1];
                }
            }
        }
        return dp[s1.Length,s2.Length];
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值