zoukankan      html  css  js  c++  java
  • 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);
        }
    }
    
  • 相关阅读:
    org.springframework.beans.BeanUtils属性赋值 Date类型处理转换为LocalDateTime, Date不能直接赋值给LocalDateTime
    python rabbitmq官方文档demo
    rabbitmq安装
    python 文件查找及截取字符串 (替换,分割) demo
    python pika rabbitmq demo
    python xlrd excel读取操作
    python pymysql 数据库查询操作
    GO语言学入门学习,学习资料推荐
    linux安装uwsgi错误:gcc returned 1 exit status error: lto-wrapper failed collect2:
    anconda的使用以及在conda环境中使用pip和conda使用安装依赖的区别和注意事项
  • 原文地址:https://www.cnblogs.com/yfs123456/p/12616744.html
Copyright © 2011-2022 走看看