Java数据结构与算法之交错字符串97(DP)

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

思路分析

当我看到这道题的第一想法是用三指针的方法解决:index1指向s1index2指向s2index3指向s3。按照顺序判断s3的字符是否与s1、s2的字符一致,即先与s1判断,不一致再与s2判断;若都不一样则输出false
但这个解法在随后的测试中暴露了问题,与s1、s2比较是存在先后顺序的,所以如果s2出现s3的前部,则会出现问题。
比如"aa" "ab" "abaa"这个案例中,结果显示false,明显是错误的。

所以基于以上的问题,我们重新考虑问题。使用动态规划解题。我们依旧使用上面的案例进行解释。

  1. 首先考虑边界条件,s1.length()+s2.length() != s3.length()这种情况那么必然输入false;

  2. s1.length()+s2.length() == s3.length()时,我们可以利用DP思想解决这个问题;

  3. 定义dp[i][j]s1的前i个元素和s2的前j个元素是否可以组合成s3的前i+j个元素;

  4. 因此想要判断dp[i][j]位置的状态需要知道dp[i-1][j]dp[i][j-1]的状态,换言之,只有dp[i-1][j]dp[i][j-1]true才会有dp[i][j]的进一步判断;

  5. dp[i-1][j]代表s1的前i-1个元素和s2的前j个元素的组合状态。那么s1的第i-1元素呢,它是否可以组合为s3的第i+j-1元素呢?

  6. 所以dp[i-1][j]s1.charAt(i-1) == s3.charAt(i+j-1)才是dp[i][j]的真实状态;反之dp[i][j-1]亦然;

  7. DP的初始状态dp[0][0]必然为true

所以我们可以推导出动态规划方程为: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))

代码实现

class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
        int index1 = s1.length(), index2 = s2.length();
        if(s3.length() != index1+index2) {
            return false;
        }

        boolean[][] dp = new boolean[index1+1][index2+1];
        dp[0][0] = true;

            // 为什么这儿要从0开始遍历呢?这就是三指针的问题所在。
            // 当s3的开头字符是s2,这样在i=0的情况下就可以先搜索s2字符串了。
        for(int i = 0; i <= index1; i++) {
            for(int j = 0; j <= index2; j++) {
                int p = i+j-1;
                if(i > 0) {
                        // 这儿不加dp[i][j]的原因是先判断if(i > 0)
                        // 如果i<0,那么dp[i][j]就是默认值false,不影响下面的执行
                    dp[i][j] = dp[i-1][j] && s1.charAt(i-1) == s3.charAt(p);
                }
                if(j > 0) {
                        // 这儿为什么要加dp[i][j]?
                        // 如果在if(i > 0)中已经判断为true了,则不用再判断了
                        // 如果在if(i > 0)中已经判断为false了,则继续判断在if(j > 0)条件下是否满足
                    dp[i][j] = dp[i][j] || dp[i][j-1] && s2.charAt(j-1) == s3.charAt(p);
                }
            }
        }
        return dp[index1][index2];
    }
}

执行结果

原文地址:https://www.cnblogs.com/njuptzheng/p/13338257.html