力扣第九十七题-交错字符串

「这是我参与11月更文挑战的第17天,活动详情查看:2021最后一次更文挑战

前言

力扣第九十七题 交错字符串 如下所示:

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

两个字符串 s 和 t 交错 的定义与过程如下,其中每个字符串都会被分割成若干 非空 子字符串:

  • s = s1 + s2 + ... + sn
  • t = t1 + t2 + ... + tm
  • |n - m| <= 1
  • 交错 是 s1 + t1 + s2 + t2 + s3 + t3 + ... 或者 t1 + s1 + t2 + s2 + t3 + s3 + ...

提示: a + b 意味着字符串 a 和 b 连接。

示例 1:

输入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
输出: true
复制代码

一、思路

题目的意思很清楚,就是:**判断 s1 中若干的子串与 s2 中若干的子串组合,是否能构成 s3 **

很明显要满足以下的条件:

  • s1.len + s2.len == s3.lens1s2 的长度相加要等于 s3 的长度
  • s1s2 的字符个数要与 s3 中的字符个数相等

我们不妨假设 s11 ~ i 可以与 s2 中的 1 ~ j 构成交错字符串,如下图所示:

注意:这里的 ij 是指元素的位置(或个数)从 1 开始,并不为数组中的下标

image.png

如果此时 s3 中第 i+j+1 这个元素为 c,请问 s1s2 添加什么元素可以再使:

  • s11 ~ i+1s2 中的 1 ~j 构成交错字符串 s3 (1 ~ i+j+1)
  • s11 ~ is2 中的 1 ~j+1 构成交错字符串 s3 (1 ~ i+j+1) 呢?

其实答案很明显:就是在 s1 的末尾叫上 cs2 的末尾加上 c 即可,如下图所示:

image.png

通过上面的推理我们发现 s11~i 个字符与 s21~j 个字符是否构成交错字符,是根据他们各自的子串 1~i-11~j1~i1~j-1 是否构成交错字符有关。这就与动态规划的思想不谋而合了。

假设 dp[i][j]s1 中的 1~is2 中的 1~j 是否构成交错字符,根据上面的推理,我们很容易就可以得到状态转移方程

dp[i][j] = (dp[i-1][j] && s1[i] == s3[i+j]) || (dp[i][j-1] && s2[j] == s3[i+j])

既然有了思路,那么实现代码就是一个自底向上的过程了。

二、实现

实现代码

我们要在遍历前,先初始化边界值

    public boolean isInterleave(String s1, String s2, String s3) {
        int len1 = s1.length();
        int len2 = s2.length();
        int len3 = s3.length();
        // 如果长度不等,则一定不为交错字符串
        if(len1 + len2 != len3)
            return false;
        boolean[][] dp = new boolean[len1+1][len2+1];
        // 初始化边界
        dp[0][0] = true;
        // 初始化第一列和第一行
        for (int i=1; i<=len2; i++) {
            dp[0][i] = s2.charAt(i-1) == s3.charAt(i-1) && dp[0][i-1];
        }
        for (int i=1; i<=len1; i++) {
            dp[i][0] = s1.charAt(i-1) == s3.charAt(i-1) && dp[i-1][0];
        }
        // 根据状态转移方程填充dp即可
        for (int i=1; i<=len1; i++) {
            for (int j=1; j<=len2; j++) {
                dp[i][j] = (dp[i-1][j] && s1.charAt(i-1) == s3.charAt(i+j-1)) ||
                        (dp[i][j-1] && s2.charAt(j-1) == s3.charAt(i+j-1));
            }
        }
        return dp[len1][len2];
    }
复制代码

测试代码

    public static void main(String[] args) {
        new Number97().isInterleave("db","b", "cbb");
    }
复制代码

结果

image.png

三、总结

感谢看到最后,非常荣幸能够帮助到你~♥

如果你觉得我写的还不错的话,不妨给我点个赞吧!如有疑问,也可评论区见~

おすすめ

転載: juejin.im/post/7031515343105294349