个人记录-LeetCode 97. Interleaving String

来源:互联网 发布:java main sleep 编辑:程序博客网 时间:2024/06/08 14:21

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

For example,
Given:
s1 = “aabcc”,
s2 = “dbbca”,

When s3 = “aadbbcbcac”, return true.
When s3 = “aadbbbaccc”, return false.

题目的含义是:
有两个字符串s1和s2,每次从这两个字符串的一个中,取出一个字符(从前往后取),
添加到新的字符串中,直到两个字符串都取完。

显然,由于每次都可以随机选取,因此最终可能生成许多不同的新字符串。
现在,需要判断s3是否为这些生成的新字符串中的一个。


代码示例:
1、比较容易想到的是,暴力递归,虽然可行,但会超时。

public class Solution {    public boolean isInterleave(String s1, String s2, String s3) {        //首先保证s1、s2的长度和等于s3的长度, 在innerHelper中完成递归 (假设s1、s2和s3不为null)        return (s1.length() + s2.length() == s3.length()) && innerHelper(s1, s2, s3);    }    private boolean innerHelper(String s1, String s2, String s3) {        int len1 = s1.length();        int len2 = s2.length();        int len3 = s3.length();        if (len1 == 0 && len2 == 0 && len3 == 0) {            return true;        }        char temp = s3.charAt(0);        String s1Sub = len1 > 1 ? s1.substring(1) : "";        String s2Sub = len2 > 1 ? s2.substring(1) : "";        String s3Sub = len3 > 1 ? s3.substring(1) : "";        //这里的思路主要是,从s3中取出第一个字符        //判断这个字符是否与s1、s2的首位相等        //如果相等,就接着比较子串        //最终,没有子串可继续比较时,就说明s3为Interleaving String        if (len1 > 0 && len2 > 0) {            if(s1.charAt(0) == temp && s2.charAt(0) == temp) {                return innerHelper(s1Sub, s2, s3Sub) || innerHelper(s1, s2Sub, s3Sub);            } else if (s1.charAt(0) == temp) {                return innerHelper(s1Sub, s2, s3Sub);            } else if (s2.charAt(0) == temp) {                return innerHelper(s1, s2Sub, s3Sub);            }        } else if (len1 == 0 && len2 > 0) {            return (s2.charAt(0) == temp) && innerHelper(s1, s2Sub, s3Sub);        } else if (len1 > 0 && len2 == 0){            return (s1.charAt(0) == temp) && innerHelper(s1Sub, s2, s3Sub);        }        return false;    }}

2、DP
LeetCode中,字符串的比对,基本上都需要靠DP才能解决。

public class Solution {    public boolean isInterleave(String s1, String s2, String s3) {        //同样,首先保证长度符合条件        if (s1.length() + s2.length() != s3.length()) {            return false;        }        int n1 = s1.length();        int n2 = s2.length();        //定义dp数组,dp[i][j]表示s3中(i+j)长度的子串        //是否为由s1中i长度,s2中j长度子串构成的Interleaving串        boolean[][] dp = new boolean[n1+1][n2+1];        //当i,j均为0时,s3长度也为0,于是值为true        dp[0][0] = true;        //当j为0时,即s2长度为0,那么s3必须完全与s1相等,才能成为Interleaving串        for (int i = 1; i <= n1; ++i) {            //此时,dp[i][0]由截至前一位的值,与当前位的匹配情况来决定            dp[i][0] = dp[i-1][0] && (s1.charAt(i - 1) == s3.charAt(i - 1));        }        //同理,当i为0时,即s1长度为0,那么s3必须完全与s2相等,才能成为Interleaving串        for (int j = 1; j <= n2; ++j) {            dp[0][j] = dp[0][j-1] && (s2.charAt(j-1) == s3.charAt(j-1));        }        //至此,dp数组的两条边已经确定完毕        for (int i = 1; i <= n1; ++i) {            for (int j = 1; j <= n2; ++j) {                //现在来定义递推公式                //如果s3中的(i+j)位是从s1中取出的,那么dp[i][j]的值由dp[i-1][j]、及s1中的第i位,s3中的i+j位决定                dp[i][j] = (dp[i-1][j] && s1.charAt(i - 1) == s3.charAt(i - 1 + j))                        //如果s3中的(i+j)位是从s2中取出的,那么那么dp[i][j]的值由dp[i][j-1]、及s2中的第j位,s3中的i+j位决定                        || (dp[i][j-1] && s2.charAt(j - 1) == s3.charAt(j - 1 + i));            }        }        //dp[n1][n2]保存的就是完整长度的字符串的匹配情况        return dp[n1][n2];    }}
0 0
原创粉丝点击