Lesson 196 of 250
97. Interleaving String
NeetCode: Interleaving String · LeetCode: 97. Interleaving String · Difficulty: Medium
Given strings s1, s2 and s3, return true if s3 is formed by interleaving s1 and s2: both are split into substrings that are then merged alternately, and the characters of each original string keep their relative order.
Example
Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac" Output: true
Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc" Output: false
Input: s1 = "", s2 = "", s3 = "" Output: trueBrute force: try both strings at every position
After using i characters of s1 and j of s2, the next character of s3 is at index i + j. It can come from s1[i] if they match, or from s2[j] if they match. Try both; if both match the recursion branches. Lengths must add up first, otherwise the answer is immediately false. Without memory the branching repeats the same (i, j) pairs.
class Solution {
private boolean go(String a, String b, String c, int i, int j) {
if (i + j == c.length()) {
return true;
}
char ch = c.charAt(i + j);
return (i < a.length() && a.charAt(i) == ch && go(a, b, c, i + 1, j))
|| (j < b.length() && b.charAt(j) == ch && go(a, b, c, i, j + 1));
}
public boolean isInterleave(String s1, String s2, String s3) {
if (s1.length() + s2.length() != s3.length()) {
return false;
}
return go(s1, s2, s3, 0, 0);
}
}
public class Main {
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.isInterleave("aabcc", "dbbca", "aadbbcbcac"));
System.out.println(sol.isInterleave("aabcc", "dbbca", "aadbbbaccc"));
System.out.println(sol.isInterleave("", "", ""));
System.out.println(sol.isInterleave("", "", "a"));
System.out.println(sol.isInterleave("a", "", "a"));
}
}true
false
true
false
trueTime: O(2^(m+n)) in the worst case. Space: O(m + n).
Better: 2D table
dp[i][j] is true when the first i characters of s1 and the first j of s2 can interleave into the first i + j characters of s3. It is true if the last character of s3's prefix came from s1 (dp[i-1][j] is true and s1[i-1] matches) or from s2 (dp[i][j-1] is true and s2[j-1] matches). There are only (m + 1) * (n + 1) states.
class Solution {
public boolean isInterleave(String s1, String s2, String s3) {
int m = s1.length(), n = s2.length();
if (m + n != s3.length()) {
return false;
}
boolean[][] dp = new boolean[m + 1][n + 1];
dp[0][0] = true;
for (int i = 0; i <= m; i++) {
for (int j = 0; j <= n; j++) {
if (i == 0 && j == 0) {
continue;
}
char ch = s3.charAt(i + j - 1);
boolean fromA = i > 0 && dp[i - 1][j] && s1.charAt(i - 1) == ch;
boolean fromB = j > 0 && dp[i][j - 1] && s2.charAt(j - 1) == ch;
dp[i][j] = fromA || fromB;
}
}
return dp[m][n];
}
}
public class Main {
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.isInterleave("aabcc", "dbbca", "aadbbcbcac"));
System.out.println(sol.isInterleave("aabcc", "dbbca", "aadbbbaccc"));
System.out.println(sol.isInterleave("", "", ""));
System.out.println(sol.isInterleave("", "", "a"));
System.out.println(sol.isInterleave("a", "", "a"));
}
}true
false
true
false
trueTime: O(m · n). Space: O(m · n).
Optimal: one rolling row
Row i only depends on row i - 1 (the value directly above) and its own left neighbour. Keep one array dp[j]; when processing cell j, dp[j] still holds the value from the previous row and dp[j - 1] is already the new value for this row.
class Solution {
public boolean isInterleave(String s1, String s2, String s3) {
int m = s1.length(), n = s2.length();
if (m + n != s3.length()) {
return false;
}
boolean[] dp = new boolean[n + 1];
dp[0] = true;
for (int j = 1; j <= n; j++) {
dp[j] = dp[j - 1] && s2.charAt(j - 1) == s3.charAt(j - 1);
}
for (int i = 1; i <= m; i++) {
dp[0] = dp[0] && s1.charAt(i - 1) == s3.charAt(i - 1);
for (int j = 1; j <= n; j++) {
char ch = s3.charAt(i + j - 1);
boolean fromA = dp[j] && s1.charAt(i - 1) == ch; // dp[j] is still the row above
boolean fromB = dp[j - 1] && s2.charAt(j - 1) == ch; // dp[j - 1] is already this row
dp[j] = fromA || fromB;
}
}
return dp[n];
}
}
public class Main {
public static void main(String[] args) {
Solution sol = new Solution();
System.out.println(sol.isInterleave("aabcc", "dbbca", "aadbbcbcac"));
System.out.println(sol.isInterleave("aabcc", "dbbca", "aadbbbaccc"));
System.out.println(sol.isInterleave("", "", ""));
System.out.println(sol.isInterleave("", "", "a"));
System.out.println(sol.isInterleave("a", "", "a"));
}
}true
false
true
false
trueTime: O(m · n). Space: O(n).
