Problem
LeetCode 97. Interleaving String
Difficulty : Hard
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.
Example 1:
1 | Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac" |
Example 2:
1 | Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc" |
Analysis
这一周依然来做一道动态规划的问题,题目要求判断给出的字符串是否是两个字符串的交错组成。很明显,这就是一道动态规划的问题。
Approach 1
对于动态规划的题目,首先,需要先把问题划分为更小的子问题。
这里的问题定义为E(i, j)
,表示第一个字符串的前i
个字符和第二个字符串的前j
个字符是否可以交错形成第三个字符串的前i + j
个字符。
而这个问题的答案只有两种成立的可能性:
- 第一个字符串的第
i
个字符等于目标字符串的第i + j
个字符,并且E(i -1, j)
成立,也就是说- $S_1(i) == S_3(i + j) && E(i - 1, j)$
- 第二个字符串的第
j
个字符等于目标字符串的第i +j
个字符,并且E(i, j - 1)
成立,也就是说- $S_2(i) == S_3(i + j) && E(i , j - 1)$
然后定义最小的子问题,E(i, 0)
和E(0, j)
前者代表着第一个字符串的前i
个字符都与目标字符串匹配,因此可以简单地表示为
$E(i, 0) = S_1(i) == S_3(i) && E(i - 1, 0)$
后者也是类似的表达方法。
这样,我们就使用动态规划的方法构建出一个$(i + 1) \times (j + 1)$的矩阵
我们来看题目的两个例子:
Input: s1 = “aabcc”, s2 = “dbbca”, s3 = “aadbbcbcac”
Output: true
1 0 0 0 0 0
1 0 0 0 0 0
1 1 1 1 1 0
0 1 1 0 1 0
0 0 1 1 1 1
0 0 0 1 0 1我们可以看到矩阵里面有一条从左上角到右下角的标号为 1 的路径,表示存在至少一种的方法可以交错构建出目标字符串
Input: s1 = “aabcc”, s2 = “dbbca”, s3 = “aadbbbaccc”
Output: false
1 0 0 0 0 0
1 0 0 0 0 0
1 1 1 1 0 0
0 1 1 1 0 0
0 0 0 0 0 0
0 0 0 0 0 0这里并不存在路径
最后矩阵的右下角就表示是否可以交错构建出目标字符串。
C++代码如下:
1 | class Solution { |
这个算法需要遍历两个数组组成的矩阵,时间复杂度为O(nm)
,空间复杂度为O(nm``)
n
和m
分别是两个字符串的长度。
Summary
这是一道非常传统并且经典的动态规划问题,相信只要学过动态规划就很容易可以解决。