[LeetCode] Interleaving String - 交织的字符串
题目如下: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"'。那么我们的判断逻辑大概会是这样子:
- 如果s1的第一位和s3的第一位相同,则比较s2的第二位和s3的第二位,如果也相同则成立。
- 如果s2的第一位和s3的第一位相同,则比较s1的第二位和s3的第二位,如果也相同则成立。
- 没有符合条件的,则不成立。
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 - 交织的字符串的更多相关文章
- [LeetCode] Interleaving String 交织相错的字符串
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example, Given: s1 ...
- Leetcode:Interleaving String 解题报告
Interleaving StringGiven s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For ...
- [LeetCode] 97. Interleaving String 交织相错的字符串
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1and s2. Example 1: Input: s1 = ...
- [LeetCode] Interleaving String 解题思路
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Given:s1 = ...
- [LeetCode] Interleaving String [30]
题目 Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example, Given: ...
- [LeetCode] Reverse String II 翻转字符串之二
Given a string and an integer k, you need to reverse the first k characters for every 2k characters ...
- Interleaving String,交叉字符串,动态规划
问题描述: Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Give ...
- [Leetcode] Interleaving String
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Given:s1 = ...
- [leetcode]Interleaving String @ Python
原题地址:https://oj.leetcode.com/problems/interleaving-string/ 题意: Given s1, s2, s3, find whether s3 is ...
随机推荐
- Flash: An Efficient and Portable Web Server
Introduction This paper presents the design of a new Web server architecture called the asymmetric m ...
- angular之上滑换页指令
healthmallDirectives.directive("goodsTopRefresh", ['$window',function ($window) { return { ...
- Spring的事务管理
事务 事务:是逻辑上一组操作,要么全都成功,要么全都失败. 事务特性(ACID) 原子性:事务不可分割 一致性:事务执行的前后,数据完整性保持一致 隔离性:一个事务执行的时候,不应该受到其他事务的打扰 ...
- css3选择器
原网站 cnblogs.com/tianshang/p/5982513.html通配符选择器 通配选择器的作用就是对页面上所有的元素都生效, 页面上的所有标签都会展示出通配符选择器设定的样式. 这样的 ...
- 前端项目通用、常用js common.js
var url = location.href; if (url.toLowerCase().indexOf("/akweb_admin/") == -1) { function ...
- Dos命令查看端口占用及关闭进程
1. 查看端口占用 在windows命令行窗口下执行: netstat -aon|findstr "8080" TCP 127.0.0.1:80 0.0.0.0:0 LISTENI ...
- JavaScript高级程序设计-(2)基础概念
for-in 语句 for-in 语句是一种迭代语句,用来枚举对象属性,语法:for (property in expression) statement实例:for(var propName in ...
- npm-async使用
async.series(tasks, callback) tasks可以是对象或数组,返回类型就是参数类型 tasks中传入回调函数的第一个值非空即停止后面函数执行 按照顺序流程进行 async.s ...
- JavaScript(三) 正则表达式 以及实现的功能
RegExp 是正则表达式的缩写.定义RegExp正则表达式 RegExp 对象用于存储检索模式. 通过 new 关键词来定义 RegExp 对象.以下代码定义了名为 p 的 RegExp 对象,其模 ...
- Hoops随便记的
段 包含图形的段·几何·属性:颜色,可见性,选择功能等等·子段:更低层的段段的名称·段可以进行命名·可以像文件系统一样表示路径:绝对路径.相对路径.通配符当前段(激活的段)·你可以在任何一个时间来处理 ...