首页 > 其他 > 详细

leetcode 97.交错字符串

时间:2020-04-02 00:05:53      阅读:76      评论:0      收藏:0      [点我收藏+]

题目描述

给定三个字符串?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);
    }
}

leetcode 97.交错字符串

原文:https://www.cnblogs.com/yfs123456/p/12616744.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!