题目如下: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. Beginning Scala study note(2) Basics of Scala

    1. Variables (1) Three ways to define variables: 1) val refers to define an immutable variable; scal ...

  2. 对于挑战书上的很久之前都看不懂的DP看懂的突破

    突破一..牢记问题概念 并且牢记dp状态方程 突破二..一直有一个求和dp转化成O1dp递推的式子看不懂.. 看不懂的原因是..没有分清求和符号作用的范围 提醒:以后遇到求和符号一定明确其求和的式子的 ...

  3. 进击的Python【第三章】:Python基础(三)

    Python基础(三) 本章内容 集合的概念与操作 文件的操作 函数的特点与用法 参数与局部变量 return返回值的概念 递归的基本含义 函数式编程介绍 高阶函数的概念 一.集合的概念与操作 集合( ...

  4. 1.4 jQuery方法,JSON介绍

    jQuery方法: jQuery添加元素: append()方法: $("元素").append("追加内容"); prepend()方法: $("元 ...

  5. Codeforces Round #388 (Div. 2) - C

    题目链接:http://codeforces.com/contest/749/problem/C 题意:给定一个长度为n的D/R序列,代表每个人的派别,然后进行发表意见,顺序是从1到n.每个人到他的回 ...

  6. 搭建ssm的领悟

    今天搭建了ssm,但是一直报错误 "Cannot load JDBC driver class 'com.mysql.jdbc.Driver" 我以为是版本的问题就换,以为是路径加 ...

  7. haha3

    YOU - fhasd - fdks jf > jd sfkjd sf </div><div><span >print "helloworld&qu ...

  8. Lession1 写在机器学习之前

    机器学习从学习方式上来讲,可以分为两类: 监督学习(Supervised Learning),简而言之就是“有标签”学习 无监督学习(Unsupervised Learning),简而言之就是“无标签 ...

  9. bootstrap之HTML模板

    bootstrap之HTML模板 <!DOCTYPE html> <html> <head> <title>Bootstrap 模板</title ...

  10. JavaScript_js模拟键盘输入

    function fireKeyEvent(el, evtType, keyCode) { var evtObj; if (document.createEvent) { if (window.Key ...