剑指 Offer II 096. 字符串交织(97. 交错字符串)

题目:

 

 

 

思路:

【1】利用递归的方式:

递归的原理:
递归本质上就是拆分,你也可以想象成树一样
如s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
本质上aad这部分是没有异议的,毕竟只有他们匹配
那么剩下的便会是s1 = "bcc", s2 = "bbca", s3 = "bbcbcac"
所以这个b应该选哪个呢?故应该两个都尝试
分为
s1填充后:s1 = "cc", s2 = "bbca", s3 = "bcbcac"
s2填充后:s1 = "bcc", s2 = "bca", s3 = "bcbcac"
那么再按这种思路一路走下去,只要有一条路可以,那么便应该返回true。

 

【2】动态规划的方式

代码展示:

动态规划的方式:

//时间5 ms击败36.63%
//内存39.8 MB击败39.76%
//标准的动态规划
//时间复杂度和空间复杂度都是 O(nm)
class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
        int n = s1.length(), m = s2.length(), t = s3.length();

        if (n + m != t) return false;
        boolean[][] f = new boolean[n + 1][m + 1];
        f[0][0] = true;

        for (int i = 0; i <= n; ++i) {
            for (int j = 0; j <= m; ++j) {
                int p = i + j - 1;
                if (i > 0) {
                    f[i][j] = f[i][j] || (f[i - 1][j] && s1.charAt(i - 1) == s3.charAt(p));
                }
                if (j > 0) {
                    f[i][j] = f[i][j] || (f[i][j - 1] && s2.charAt(j - 1) == s3.charAt(p));
                }
            }
        }
        return f[n][m];
    }
}

//当然动态规划是可以进行优化的
//时间3 ms击败63.95%
//内存39.6 MB击败66.68%
class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
        int n = s1.length(), m = s2.length(), t = s3.length();

        if (n + m != t) return false;
        boolean[][] f = new boolean[n + 1][m + 1];
        f[0][0] = true;
        for (int i = 0; i <= n; ++i) {
            for (int j = 0; j <= m; ++j) {
                int p = i + j - 1;
                if (i > 0) {
                    f[i][j] = f[i][j] || (f[i - 1][j] && s1.charAt(i - 1) == s3.charAt(p));
                }
                if (j > 0) {
                    f[i][j] = f[i][j] || (f[i][j - 1] && s2.charAt(j - 1) == s3.charAt(p));
                }
            }
        }

        return f[n][m];
    }
}

 

利用递归的方式:

//时间0 ms击败100%
//内存39.7 MB击败56.76%
//可以看出使用递归虽然能解,但是空间复杂度达不到进阶的程度
class Solution {
    int l1, l2, l3;
    String s1, s2, s3;
    boolean[][] visited;
    public boolean isInterleave(String s1, String s2, String s3) {
        l1 = s1.length();
        l2 = s2.length();
        l3 = s3.length();
        if (l1 + l2 != l3)  return false;
        visited = new boolean[l1 + 1][l2 + 1];
        this.s1 = s1;
        this.s2 = s2;
        this.s3 = s3;
        
        return dfs(0, 0, 0);
    }
    private boolean dfs(int i, int j, int k) {
        if (k == l3)    return true;
        if (visited[i][j])  return false;
        visited[i][j] = true;
        if (i < l1 && s1.charAt(i) == s3.charAt(k) && dfs(i + 1, j, k + 1))         return true;   
        if (j < l2 && s2.charAt(j) == s3.charAt(k) && dfs(i, j + 1, k + 1))         return true;
        return false;
    }
}

 

一开始以为是随意匹配的,然后运行的时候才发现其实是保留原本的顺序,也就是在相对顺序不变的情况下进行组合(这个代码其实是不过的):

如:输入"aabcc" 和 "dbbca" 和 "aadbbbaccc" 发现相对顺序不行是不过的,虽然字符都能一一对应

class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
        if (s3 == "" && s1 == "" && s2 == "") return true;
        int[] flag = new int[26];
        int index1 = 0, index2 = 0;
        while (index1 < s1.length() || index2 < s2.length()){
            if (index1 < s1.length()) flag[s1.charAt(index1++) - 'a']++;
            if (index2 < s2.length()) flag[s2.charAt(index2++) - 'a']++;
        }
        for (int i = 0; i < s3.length(); i++){
            if (--flag[s3.charAt(i) - 'a'] < 0) return false;
        }
        return true;
    }
}

 

posted @ 2023-03-15 15:03  忧愁的chafry  阅读(31)  评论(0编辑  收藏  举报