097-interleaving-string
Question
https://leetcode.com/problems/interleaving-string/description/
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.
Example:
Given:
s1 = "aabcc",
s2 = "dbbca",
When s3 = "aadbbcbcac", return true.
When s3 = "aadbbbaccc", return false.
Thought Process
- Recursion (TLE)
- From two strings, we can pick either one from s1 and s2
- For tracking usage of the characters from s1 and s2, we use two variables i and j
- As long we i and j is smaller than the length, we can add the character and recurse
- Time complexity O(2^(m + n))
- Space complexity O(2^(m+n)) due to recursiong
- Recursion with Memo
- Using three variables to track s1, s2 and s3
- When either i or j reach the end, we just need to check the rest of the other string
- Time complexity O(m + n)
- Space complexity O(mn) for memo and O(m + n) due to recursion
- Dynamic Programing Bottom Up
- Create dp array of dimension m + 1 and n + 1, where m is length of s1 and n is length of s2
- dp[i][j] indicates the possibility of using ith character of s1 or jth character of s2 for the kth character of s3, where k = i + j
- Time complexity O(mn)
- Space complexity O(mn)
- DP with Space Reduction
- Time complexity O(mn)
- Space complexity O(n)
Solution
class Solution {
public boolean isInterleave(String s1, String s2, String s3) {
if (s1.length() + s2.length() != s3.length()) return false;
return isInterleave(s1, 0, s2, 0, "", s3);
}
private boolean isInterleave(String s1, int i, String s2, int j, String res, String s3) {
if (res.equals(s3)) return true;
boolean ans = false;
if (i < s1.length() && s3.charAt(i + j) == s1.charAt(i)) {
ans |= isInterleave(s1, i + 1, s2, j, res + s1.charAt(i), s3);
}
if (j < s2.length() && s3.charAt(i + j) == s2.charAt(j)) {
ans |= isInterleave(s1, i, s2, j + 1, res + s2.charAt(j), s3);
}
return ans;
}
}
class Solution {
public boolean isInterleave(String s1, String s2, String s3) {
if (s1.length() + s2.length() != s3.length()) return false;
Boolean[][] memo = new Boolean[s1.length()][s2.length()];
return isInterleave(s1, 0, s2, 0, s3, 0, memo);
}
private boolean isInterleave(String s1, int i, String s2, int j, String s3, int k, Boolean[][] memo) {
if (i == s1.length()) return s2.substring(j).equals(s3.substring(k));
if (j == s2.length()) return s1.substring(i).equals(s3.substring(k));
if (memo[i][j] != null) return memo[i][j];
boolean ans = false;
if ((s1.charAt(i) == s3.charAt(k) && isInterleave(s1, i + 1, s2, j, s3, k + 1, memo)) || (s2.charAt(j) == s3.charAt(k) && isInterleave(s1, i, s2, j + 1, s3, k + 1, memo))) {
ans = true;
}
memo[i][j] = ans;
return ans;
}
}
class Solution {
public boolean isInterleave(String s1, String s2, String s3) {
if (s1.length() + s2.length() != s3.length()) return false;
int m = s1.length(), n = s2.length();
boolean[][] dp = new boolean[m + 1][n + 1];
dp[0][0] = true;
for (int j = 1; j <= n; j++) {
if (dp[0][j - 1] && s2.charAt(j - 1) == s3.charAt(j - 1)) dp[0][j] = true;
}
for (int i = 1; i <= m; i++) {
if (dp[i - 1][0] && s1.charAt(i - 1) == s3.charAt(i - 1)) dp[i][0] = true;
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
dp[i][j] = (dp[i][j - 1] && s2.charAt(j - 1) == s3.charAt(i + j - 1)) || (dp[i - 1][j] && s1.charAt(i - 1) == s3.charAt(i + j - 1));
}
}
return dp[m][n];
}
}
class Solution {
public boolean isInterleave(String s1, String s2, String s3) {
if (s1.length() + s2.length() != s3.length()) return false;
int m = s1.length(), n = s2.length();
boolean[]dp = new boolean[n + 1];
dp[0] = true;
for (int j = 1; j <= n; j++) {
if (dp[j - 1] && s2.charAt(j - 1) == s3.charAt(j - 1)) dp[j] = true;
}
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++) {
dp[j] = (dp[j - 1] && s2.charAt(j - 1) == s3.charAt(i + j - 1)) || (dp[j] && s1.charAt(i - 1) == s3.charAt(i + j - 1));
}
}
return dp[n];
}
}