个人记录-LeetCode 97. Interleaving String

问题:
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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值