leetcode 97.交错字符串

题目描述

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

示例 1:

输入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
输出: true
示例 2:

输入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
输出: false

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/interleaving-string
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解析

交错字符串换言之就是,s1与s2在s3中的字符顺序还和原来的一样。比如

这样的话,我们可以将s1,s2从左至右挨个按照s3的顺序取出,若能够排列出一个完整的s3那么s3就是由s1与s2交错产生的。这就是关键思路。取出字母可以分别给s1,s2分配一个游标指针i,j。子串[0..i-1],[0..j-1]表示已经取出的串str。由于是按照s3的顺序取出的,这时str[0..i-1+j-1]与s3[0..i-1+j-1]是完全相同的。为方便实现,我们给s3也分配一个游标k。
对于状态(i,j)我们有三种选择

  1. 当s1[i] == s3[k],只能选择s1[i]这个字符。让i++,k++。
  2. 当s2[j] == s3[k],只能选择s2[j]这个字符。让j++,k++。
  3. 当s1[i] == s3[k]且s2[j] == s3[k],我们既可以选择取出s1[i],也可以选择取出s2[j]。这两种方式都要试一遍才能找出最终结果。
    一直递归到i==s1.length, j == s2.length或者说k == s3.length,递归结束,这时已经可以判定s1与s2可以交错产生s3,层层返回即可。
    对于这种情况,我优先选择使用记忆化搜索,一是方便编程,而是思路清晰,容易阅读。一般情况下,记忆化不必递推慢。如何使用记忆化,首先要明白重叠子结构在哪儿,所谓记忆化就是将这种重叠子结构的结果保存下来,下次如果用到,不必再重复计算,这就是记忆化的由来。关键问题是如何找到重叠子结构,比较有效的方法是,既然已经有上述分析的思路了,那不妨一步步的画一画,将递归树画出来,重叠子结构一眼明了。

上图中红色框框中就是重叠子结构。我们将这些结果保存下来,在下次用到的时候就不用重复计算了。本题一个特殊的地方是,程序实际运行中最右边的分支是不会遍历到的。因为在中间的分支已经可以确定是否是交错产生的了。

在上图中重叠子结构有两个,在计算第二个的时候,就可以重用第一次计算的结果。
程序说明:
dp[i][j]=true表示s1[0..i-1]与s2[0..j-1]不能交错组成s3[k],这里k=i-1+j-1。

代码

public class Solution {
    private boolean[][] dp;
    private char[] s1,s2,s3;

    private boolean helper(int i, int j, int k) {
        if (i == s1.length && j == s2.length) return true;
        if (i > s1.length || j > s2.length || dp[i][j]) return false;
        if (i < s1.length && s1[i] == s3[k] && helper(i + 1, j, k + 1)) {
            return true;
        }
        if (j < s2.length && s2[j] == s3[k] && helper(i, j + 1, k + 1)) {
            return true;
        }
        dp[i][j] = true;
        return false; // s1[i] != s3[k] && s2[j] != s3[k]
    }
    // 1ms 100%(中文) 0ms 100%(英文)
    public boolean isInterleave(String s1, String s2, String s3) {
        if (s1.length()+s2.length() != s3.length()) return false;
        dp = new boolean[s1.length()+1][s2.length()+1];
        this.s1 = s1.toCharArray();
        this.s2 = s2.toCharArray();
        this.s3 = s3.toCharArray();
        return helper(0,0,0);
    }
}

猜你喜欢

转载自www.cnblogs.com/yfs123456/p/12616744.html