LeetCode 交错字符串

434 阅读2分钟

LeetCode 交错字符串

交错字符串(Interleaving String)是一道经典的动态规划问题,在LeetCode上的难度为中等(Medium)。在这篇文章中,我们将学习交错字符串的相关知识,并通过Java代码来完成该问题的解法。

问题描述

给定三个字符串 s1、s2 和 s3,判断 s3 是否由 s1 和 s2 交错组成。换句话说,当从 s1 和 s2 中轮流取字符形成字符串 s3 时,是否存在一种方法,使得 s3 中的字符顺序与 s1 和 s2 中的字符顺序一致。

例如:

输入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"

输出: true

解释:

s3 由 s1 和 s2 交错组成,其中 s1 = "aabcc",s2 = "dbbca"。因此,s3 的顺序应该是 "aabbdbccaca",我们可以轮流从 s1 和 s2 中取字符得到。

思路分析

因为 s3 的字符顺序需要和 s1、s2 中的字符顺序一致,所以在验证是否是交错字符串时,我们需要在 s1 和 s2 中轮流取出字符,然后根据顺序组合成 s3。如果 s1 和 s2 的字符顺序无法组合成 s3,那么 s3 就不是交错字符串。

我们可以使用动态规划的思想来解决这个问题。首先要明确的是,只有当 s3 的长度与 s1 和 s2 的长度之和相等时,才有可能是交错字符串。例如,当 s1 = "aabcc"、s2 = "dbbca" 时,若 s3 的长度为 8,那么 s3 就不可能由 s1 和 s2 交错组成。

假设 s1 的长度为 m,s2 的长度为 n,那么 s3 的长度为 m + n。我们使用一个二维数组 dp 来保存 s1 和 s2 的字符在 s3 中的位置信息。例如,当 dp[i][j] = k 时,表示 s3[0, k) 是 s1[0, i) 和 s2[0, j) 的交错组成,其中 0 <= i <= m,0 <= j <= n。

在动态规划的转移过程中,我们需要同时考虑 s1 和 s2 中下一个字符是否能组成 s3 的下一个字符。具体地,当 s1[i-1] == s3[i+j-1] 时,s1[i-1] 可以被加入到 s3 中,此时 dp[i][j] = dp[i-1][j] + 1;同样地,当 s2[j-1] == s3[i+j-1] 时,s2[j-1] 可以被加入到 s3 中,此时 dp[i][j] = dp[i][j-1] + 1。

最终,如果 dp[m][n] = m + n,那么 s3 就是 s1 和 s2 的交错组成,返回 true;否则,返回 false。

示例代码

根据以上思路,我们可以编写出如下的Java代码,以解决交错字符串问题:

class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
        if (s1.length() +s2.length()!=s3.length()) return false;//长度不相等时返回false
        boolean[][] dp = new boolean[s1.length()+1][s2.length()+1];
        dp[0][0] = true;
        for (int i = 0; i <= s1.length(); i++){
            for(int j = 0; j <= s2.length(); j++){
                //都不为空时的计算
                if(i>0 && dp[i-1][j] && s1.charAt(i-1) == s3.charAt(i+j-1)){
                    dp[i][j] = true;
                }
                if(j>0 && dp[i][j-1] && s2.charAt(j-1) == s3.charAt(i+j-1)){
                    dp[i][j] = true;
                }
            }
        }
        return dp[s1.length()][s2.length()];
    }
}

运行结果

我们以 s1 = "aabcc"、s2 = "dbbca"、s3 = "aadbbcbcac" 为例,来验证一下以上代码的运行结果。

Solution solution = new Solution();
boolean result = solution.isInterleave("aabcc", "dbbca", "aadbbcbcac");
System.out.println(result);

输出结果为:

true

这表明 s3 = "aadbbcbcac" 是由 s1 = "aabcc" 和 s2 = "dbbca" 交错组成的。

总结

交错字符串是一个比较经