题目如下:https://oj.leetcode.com/problems/interleaving-string/

Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.

For example, Given: s1 = "aabcc", s2 = "dbbca",

When s3 = "aadbbcbcac", return true. When s3 = "aadbbbaccc", return false.

题目很明确就是判断字符串s3是否可以由s1和s2交织组成。乍一看并不是很难,但是仔细一想并没有那么简单。

第一个想法就是首先遍历s1和s3,将s1中出现的字母在s3中删除,然后再去比较剩下来的字符串是否与s2相同。但是很明显这个想法是错误的,因为同样的字母可能出现在s1和s2中,这样子s3中某一个字母匹配的可能是s1中的也可能是s2中的,所以这种解法是错误的。

这道题目正确的解法之一是利用动态规划,在列出答案之前先写一下如何去思考这个问题。

思考路径

从小规模的问题入手

首先,先将问题的规模缩小。缩到最小,假设s1和s2分别只有一个字符,那么我们会怎么去判断s3是否由s1和s2交织而成呢?

例-1

假设s1 = "a", s2 = "b", 's3 = "ab"'。那么我们的判断逻辑大概会是这样子:

  1. 如果s1的第一位和s3的第一位相同,则比较s2的第二位和s3的第二位,如果也相同则成立。
  2. 如果s2的第一位和s3的第一位相同,则比较s1的第二位和s3的第二位,如果也相同则成立。
  3. 没有符合条件的,则不成立。
	if (s1[0] == s3[0]){
if (s2[0] == s3[1]){
return true;
}
}
if (s2[0] == s3[0]){
if(s1[0] == s3[1]){
return true;
}
}
return false;

例-2 我们将规模稍微放大,假设s1 = "a", s2 = "bb", s3 = "abb"。我们来想想这个情况我们会怎么处理呢?

按照上面的思路,写出来的逻辑就是这样子的:

	if (s1[0] == s3[0]){
if (s2[0] == s3[1]){
if (s2[1] == s3[2]){
return true;
}
}
} if (s2[0] == s3[0]){
if (s1[0] == s3[1]){
if (s2[1] == s3[2]){
return true;
}
}
if (s2[1] == s3[1]){
if (s1[0] == s3[2]){
return true;
}
}
return false;
}

但是如果想一想,我们只是在s2和s3后面加了一个字符,我们完全没有必要重新开始判断。我们在第一个例子中已经知道了s1 = "a", s2 = "b", 's3 = "ab"'的结果,我们如果这个结果不成立,我们就没有必要再做判断了。如果成立的话我们也只需要将新加进来的字符判断一下就行了,如果相等则成立,不相等则不成立。这最大程度上的利用了已有的信息避免了重复的运算。

那我们尝试把例-1中的信息保存下来,可以得到下面这个图:

这个二维数组中的某个元素matrix[i][j]的含义可以理解为:s1.substring(0,i)s2.substring(0,j)这两个字符串组成s3.substring(0,i+j-1)字符串的可能组合。那么当s1或者s2任意一个字符串的长度增长的时候,我们只需要基于已有的可能性上再去比较新增加的字符即可。比如,上面的二维数组在例-2的情况下就演化为:

从图中很容易看出,当我们在s2中增加一个'b'的时候我们只需要计算martix[0][2]和martix[1][2],而这两个值分别是根据以后的数据演化出来的。matrix[0][1] => matrix[0][2], matrix[0][2] & matrix[1][1] => matrix[1][2]

总结

从上面的两个例子中我们可以得出,当某一个s1或s2中的某一个字符串增加一个字符的时候我们可以通过已有的数据推导出来新的结果集而不需要重新进行很多计算。所以我们可以将普通的字符串拆分成小规模的问题,通过这种累积的方式得到最终的结果。

而通过上面的那个矩阵,我们可以发现,如果我们想要知道字符串s3是否由s1和s2交织组成以及如何组成,我们需要算出一个$(len(s1) + 1) * (len(s2) + 1)$的矩阵,然后计算出matrix[len(s1)][len(s2)]的结果才能够得到答案。

当我们有两个字符串s1,s2的时候,我们将s1,s2当作和例-1中一样只有一个字符为开始,然后保持s1或s2的长度不变,而慢慢增加另一个字符串的长度来慢慢填充这个矩阵。算出整个矩阵后就得到了我们需要的答案。

实践

就拿s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"为例子,我们尝试填充一个矩阵,它会是这样子的:

题目只要求判断结果,但是不需要列出可能的组合。所以我们其实没有必要存放组合,而是直接存一个布尔值判断是否有方案即可。

代码如下:

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

Reference:

[LeetCode] Interleaving String - 交织的字符串的更多相关文章

  1. [LeetCode] Interleaving String 交织相错的字符串

    Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example, Given: s1 ...

  2. Leetcode:Interleaving String 解题报告

    Interleaving StringGiven s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For ...

  3. [LeetCode] 97. Interleaving String 交织相错的字符串

    Given s1, s2, s3, find whether s3 is formed by the interleaving of s1and s2. Example 1: Input: s1 = ...

  4. [LeetCode] Interleaving String 解题思路

    Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Given:s1 = ...

  5. [LeetCode] Interleaving String [30]

    题目 Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example, Given: ...

  6. [LeetCode] Reverse String II 翻转字符串之二

    Given a string and an integer k, you need to reverse the first k characters for every 2k characters ...

  7. Interleaving String,交叉字符串,动态规划

    问题描述: Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Give ...

  8. [Leetcode] Interleaving String

    Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Given:s1 = ...

  9. [leetcode]Interleaving String @ Python

    原题地址:https://oj.leetcode.com/problems/interleaving-string/ 题意: Given s1, s2, s3, find whether s3 is ...

随机推荐

  1. JAVA中MAP值保持顺序不变

    今天在进行JAVA开发过程中,因需要使用MAP来存放数据,同时希望MAP中KEY的顺序与放入顺序保持一致. 在使用HashMap之后,发现KEY的顺序是乱序的,每次打印还不太一样.上网查询资料之后发现 ...

  2. mysql 列类型

  3. 简单animate方法的封装

    function animate(ele,json,fn){ clearInterval(ele.timer); ele.timer = setInterval(function () { var b ...

  4. 【APICloud】利用sublimetext3编写apicloud

    下载sublime text 3 安装插件 使用模糊搜索apicloud有三个插件全部下载下来 安装海马玩模拟器,这是一个安卓的模拟器,进入官网下载后直接安装就可以了. 打开sublime text ...

  5. nodejs复习01

    console 格式化 console.log("%s:%s", "a", "b") //字符串 console.log("%d. ...

  6. iOS drewRect方法

    You do not need to override this method if your view sets its content in other ways. By the time thi ...

  7. apache 服务器配制

    简介:Apache 是世界上使用量第一的Web服务器软件,可用于linux,unix,windows等平台,尤其是对Linux支持完美 Apache的优点: 功能强大,自带很多功能模块,可根据需求编译 ...

  8. .NET string字符串的截取、移除、替换、插入

    在实际开发中经常要用到string的各种截取等操作,在这里总结自己认为经常出现的.NET 字符串的截取.移除.替换.插入操作,方面以后查阅. 前台代码: <%@ Page Language=&q ...

  9. ubuntu 用apt-get 安装apache 和php 之后php不能解析的问题

    sudo apt-get install apache2 sudo apt-get install php7.0 sudo apt-get install libapache2-mod-php //关 ...

  10. php与数据库代码开发规范

    php与数据库代码开发规范 1/25/2016 6:00:31 PM php对各类变量命名规范 目录名 文件命名 局部变量命名 使用英文动词名词,用下划线作为单词的分割,所有字母均使用小写 目录 up ...