LeetCode 97. 交错字符串

题目链接

97. 交错字符串

题目分析

字符串题目,一般不考虑暴力解法,因为极有可能会出现超时的情况(主要是重复搜索次数太多
这个题很明显的就是需要我们使用动态规划去做,一开始我自己也懵逼了,三串的DP?难不成要一个三维状态数组吗,但是仔细分析了一下好像其实并不是的。
因为我们s1的长度加s2的长度必定要等于s3的长度才有可能构成交错字符串,所以我们可以利用这里的关系去把三位状态数组压缩成二维。

  • dp[i][j]代表的是s1的第i-1个字符和s2的第j-1个字符匹配到s3的第i+j-1个字符的地方是否匹配

那么我们把状态定下来之后,就是找对应的转移方程了,其转移也是非常的容易理解,这里要从上往下一个一个判断,因为存在包含关系。

  • 如果s1的当前位字符和s2的字符相等,并且s1的字符等于s3的字符,那么我们需要去判断要使用哪一个才能使得交错字符串成立,所以dp[i][j] = dp[i-1][j] || dp[i][j-1];
  • 如果s1的字符等于s3的字符,那么很明显就是要s1往前挪一步,所以dp[i][j] = dp[i-1][j];
  • s2字符相等的情况和第二点一样。

那么我们还需要base cases,因为有可能单独s1或者s2都能匹配s3,所以我们要单独把另外一个字符串为空串的情况拿出来分析。

总的来说这个题的状态转移和其他的字符串匹配很相似,也很容易就写出来了。

代码实现

class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
        if(s1.length() + s2.length() != s3.length()){
            return false;
        }
        boolean[][] dp = new boolean[s1.length()+1][s2.length()+1];
        dp[0][0] = true;
        for(int i = 0; i < s1.length(); i++){
            if(s1.charAt(i) == s3.charAt(i)){
                dp[i+1][0] = dp[i][0];
            }
        }
        for(int i = 0; i < s2.length(); i++){
            if(s2.charAt(i) == s3.charAt(i)){
                dp[0][i+1] =  dp[0][i];
            }
        }
        for(int i = 1; i < dp.length; i++){
            for(int j = 1; j < dp[i].length; j++){
                if(s1.charAt(i-1) == s2.charAt(j-1) &&  s1.charAt(i-1) == s3.charAt(i+j-1)){
                    dp[i][j] = dp[i-1][j] || dp[i][j-1];
                }else if(s1.charAt(i-1) == s3.charAt(i+j-1)){
                    dp[i][j] = dp[i-1][j];
                }else if(s2.charAt(j-1) == s3.charAt(i+j-1)){
                    dp[i][j] = dp[i][j-1];
                }
            }
        }
        return dp[dp.length-1][dp[0].length-1];
    }
}

总结

DP还是得靠自己慢慢摸索才能提升。

posted @ 2020-07-18 10:06  ZJPang  阅读(123)  评论(0编辑  收藏  举报