LeetCode—97. Interleaving String

LeetCode—97. Interleaving String

题目

https://leetcode.com/problems/interleaving-string/description/
给3个字符串,判断其中两个s1和s2是否可以不变顺序的交叉组合形成s3.
在这里插入图片描述

思路及解法

动态规划的题目。
考虑递推公式。假设使用二维数组dp[i][j]表示s3的i+j个字符是否可以由s1的i个字符和s2的j个字符组合表示,那么递推公式是一个什么情况呢?我们想dp[i][j]可以由哪几种情况而来呢?对于s3的i+j-1个字符,我们可以有两种选择:要么选s1的i-1个字符,要么选s2的j-1个字符,所以递推公式就是:
dp[i][j] = (dp[i][j - 1] && s2[j - 1] == s3[i + j - 1]) || (dp[i - 1][j] && s1[i - 1] == s3[i + j - 1])
这样,最终我们只要得到dp[s1_len][s2_len]的值就是最后的结果了。
因为是一个二维的动态规划,所以时间复杂度是O(m*n),m和n分别是s1和s2的长度。空间花费,可以看出递推式中只需要用到上一行的信息,所以我们只需要一个一维数组就可以完成历史信息的维护,为了更加优化,我们把短的字符串放在内层循环,这样就可以只需要短字符串的长度即可,所以复杂度是O(min(m,n))。
再者就是边界条件了。我们先看下面的图:
在这里插入图片描述

边界条件就是要初始化黑框的第一行和第一列,根据上面得到的递推公式,我们只需要将i和j分别置0就可以得到边界条件了。

代码

class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
        int s1_len = s1.length();
        int s2_len = s2.length();
        int s3_len = s3.length();
        if(s3_len != s1_len+s2_len) return false;
        boolean[][] dp = new boolean[s1_len+1][s2_len+1];
        dp[0][0] = true;
        for(int i=1; i<=s1_len; i++){
            dp[i][0] = dp[i-1][0] && (s1.charAt(i-1)==s3.charAt(i-1));
        }
        for(int j=1; j<=s2_len; j++){
            dp[0][j] = dp[0][j-1] && (s2.charAt(j-1)==s3.charAt(j-1));
        }
        for(int i=1; i<=s1_len; i++){
            for(int j=1; j<=s2_len; 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[s1_len][s2_len];
    }
}

猜你喜欢

转载自blog.csdn.net/pnnngchg/article/details/82891035
今日推荐