Interleaving String

06/18/2021

Basic Idea

这道题目其实就是看s1 s2 两个字符串在不改变各自内部顺序的情况下交叉在一起能不能形成s3。仔细观察的话就会发现当我们固定好s1和s2中的两个index i j 的时候,只要我们确定 s1[0:i]s2[0:j] 能够通过交叉形成 s3[0:i+j] , 那么在这之后的部分就变成了和整个问题一样的子问题,于是我们就可以使用DP的思路来解决,而 i j 就可以唯一地表示一个子问题。

这道题我们可以使用DFS with cache和DP两个解法来做,时间复杂度 O(MN),通过优化DP也可以做到O(min{M,N}) 的时间。

Java Code

DFS 解法

class Solution {
    Boolean[][] cache;
    int M, N;
    String s1, s2, s3;
    
    public boolean isInterleave(String s1, String s2, String s3) {
        if (s1.length() + s2.length() != s3.length()) {
            return false;
        }
        M = s1.length();
        N = s2.length();
        this.s1 = s1;
        this.s2 = s2;
        this.s3 = s3;
        cache = new Boolean[M + 1][N + 1];
        return dfs(0, 0);
    }
    
    private boolean dfs(int m, int n) {
        if (m == s1.length() && n == s2.length()) {
            return true;
        }
        if (cache[m][n] != null) {
            return cache[m][n];
        }
        boolean ret = false;
        for (int i = m; i < s1.length(); ++i) {
            if (s1.charAt(i) != s3.charAt(n + i)) {
                break;
            }
            ret |= dfs(i + 1, n);
        }
        for (int i = n; i < s2.length(); ++i) {
            if (s2.charAt(i) != s3.charAt(m + i)) {
                break;
            }
            ret |= dfs(m, i + 1);
        }
        cache[m][n] = ret;
        return ret;
    }
}

DP 解法

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];
        for (int i = 0; i < dp.length; ++i) {
            for (int j = 0; j < dp[0].length; ++j) {
                if (i == 0 && j == 0) {
                    dp[i][j] = true;
                }
                if (i > 0 && dp[i - 1][j]
                    && s1.charAt(i - 1) == s3.charAt(i + j - 1)) {
                    dp[i][j] = true;
                }
                if (j > 0 && dp[i][j - 1]
                   && s2.charAt(j - 1) == s3.charAt(i + j - 1)) {
                    dp[i][j] = true;
                }
                if (i > 0 && j > 0 && dp[i - 1][j - 1]) {
                    if ((s1.charAt(i - 1) == s3.charAt(i + j - 2)
                       && s2.charAt(j - 1) == s3.charAt(i + j - 1)) ||
                       (s1.charAt(i - 1) == s3.charAt(i + j - 1)
                       && s2.charAt(j - 1) == s3.charAt(i + j - 2))
                    ) {
                        dp[i][j] = true;
                    }
                }
            }
        }
        return dp[M][N];
    }
}

Last updated