97. Interleaving String

Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2.

Example 1:

Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
Output: true

Example 2:

Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
Output: false
  • easy

Reminds me the Regular Expression Matching and Wild Matching

public boolean isInterleave(String s1, String s2, String s3) {
    if(s1.length() + s2.length() != s3.length()) return false;
    HashMap<Character, Integer> map = new HashMap<>();
    for(char c : (s1+s2).toCharArray())
        map.put(c, map.getOrDefault(c, 0)+1);
    for(char c : s3.toCharArray()) {
        if(!map.containsKey(c)) return false;
        map.put(c, map.get(c)-1);
    }
    for(int i : map.values()) if(i != 0) return false;
    int[][] memo = new int[s1.length()+1][s2.length()+1];
    return check(s1, s2, s3, memo);
}
public boolean check(String s1, String s2, String s3, int[][] memo) {
    if(memo[s1.length()][s2.length()] != 0) return memo[s1.length()][s2.length()] == 1;
    if((s1+s2).equals(s3) || (s2+s1).equals(s3)) return true;
    if(s1.length() == 0 || s2.length() == 0) return false;
    boolean result = false;
    if(s1.charAt(0) == s3.charAt(0))
        result |= check(s1.substring(1), s2, s3.substring(1), memo);
    if(!result && s2.charAt(0) == s3.charAt(0))
        result |= check(s1, s2.substring(1), s3.substring(1), memo);
    memo[s1.length()][s2.length()] = result ? 1 : 2;
    return result;
}
  • DP Version

public boolean isInterleave(String s1, String s2, String s3) {
    if(s1.length() + s2.length() != s3.length()) return false;
    HashMap<Character, Integer> map = new HashMap<>();
    for(char c : (s1+s2).toCharArray())
        map.put(c, map.getOrDefault(c, 0)+1);
    for(char c : s3.toCharArray()) {
        if(!map.containsKey(c)) return false;
        map.put(c, map.get(c)-1);
    }
    for(int i : map.values()) if(i != 0) return false;


    boolean[][] dp = new boolean[s1.length()+1][s2.length()+1];
    dp[0][0] = true;
    for(int i = 1; i <= s1.length(); i++) dp[i][0] = s3.startsWith(s1.substring(0,i));
    for(int i = 1; i <= s2.length(); i++) dp[0][i] = s3.startsWith(s2.substring(0,i));
    for(int k = 2; k <= s3.length(); k++) {
        for(int i = k-s2.length() > 1 ? k-s2.length() : 1; i < k && i <= s1.length(); i++) {
            int j = k - i;
            dp[i][j] = (dp[i-1][j] && s1.charAt(i-1) == s3.charAt(k-1)) || (dp[i][j-1] && s2.charAt(j-1) == s3.charAt(k-1));
        }
    }
    return dp[s1.length()][s2.length()];
}