• 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];
        }
    }
    

    执行结果

  • 相关阅读:
    6.5 列出当前目录所有文件
    6.4 协程写文件
    6.3 写文件
    6.2 创建空目录
    6.1 os 获取文件状态
    5.13 json
    es2016
    短路原理
    fexbox
    vue @
  • 原文地址:https://www.cnblogs.com/njuptzheng/p/13338257.html
Copyright © 2020-2023  润新知