Interleaving String

https://oj.leetcode.com/problems/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.


public boolean isInterleave(String s1, String s2, String s3)


其实如果你们是按顺序做一路做到这里,看到这样的题目第一反应大概就是DP题了。这一题在OJ里面属于比较简单的DP题。整个推导式都比较容易思考。其实我一直在想DP的推导式怎么才能弄出来,是不是有规律可循?其实也不尽然,当你懂的一些DP的基本规律,剩下的都是积累题目数量而产生的感觉。当然,一些比较高级的DP概念还有待我们继续学习。。譬如插头DP什么的,真是搞不懂。。


这题的概念其实也是很清晰的,就是给定两个index,i和j分别表示我们跑到了s1和s2的什么地方了。然后看看是否能s3的i + j那一点配对,能的话就OK往下走,不能的话那就对不起了,你就只能走到这里了。基于这个简单的概念,我们可以得到推导式如下

f(i, j) = s1[i] == s3[i + j] && f(i - 1, j) || s2[j] == s3[i +j] && f(i, j - 1)

base case大家自己想吧。其实也不难想。

按照国际惯例,首先放出来的是一则暴力递归外加截枝,可以AC的代码段。

    public boolean isInterleave(String s1, String s2, String s3) {
        if(s3.length() != s1.length() + s2.length())
            return false;
        byte[][] cached = new byte[s1.length() + 1][s2.length() + 1]; //用来截枝,0表示没走过,1表示true,-1表示false
        return helper(s1, s2, s3, cached, 0, 0);
    }
    
    public boolean helper(String s1, String s2, String s3, byte[][] cached, int i, int j){
        if(i == s1.length() && j == s2.length())
            return true;
        if(cached[i][j] != 0)//截枝部分,注意我的做法是bottom-top,这一题你 top-bottom是没办法截枝的了。
            return cached[i][j] == 1 ? true : false;
        boolean res = false;
        if(i != s1.length() && s1.charAt(i) == s3.charAt(i + j))
            res |= helper(s1, s2, s3, cached, i + 1, j);
        if(!res && j != s2.length() && s2.charAt(j) == s3.charAt(i + j))//!res这个判断算一个小截枝,如果上面一步已经成功了,就没必要验证这里了。
            res |= helper(s1, s2, s3, cached, i, j + 1);
        cached[i][j] = res ? (byte)1 : (byte)-1;
        return res;
    }

再来就是dp解了:

    public boolean isInterleave(String s1, String s2, String s3) {
        if(s3.length() != s1.length() + s2.length())
            return false;
        boolean[][] dp = new boolean[s1.length() + 1][s2.length() + 1];
        dp[0][0] = true;//base case,空子串和空子串弄起来那肯定也是空子串....
        for(int i = 0; i < s1.length(); i++){ 
            dp[i + 1][0] = dp[i][0] && s1.charAt(i) == s3.charAt(i);
        }
        for(int i = 0; i < s2.length(); i++){
            dp[0][i + 1] = dp[0][i] && s2.charAt(i) == s3.charAt(i);
        }
        
        for(int i = 1; i <= s1.length(); i++){
            for(int j = 1; j <= s2.length(); j++){
                dp[i][j] = (dp[i - 1][j] && s1.charAt(i - 1) == s3.charAt(i + j - 1)) || (dp[i][j - 1] && s2.charAt(j - 1) == s3.charAt(i + j - 1));
            }
        }
        return dp[s1.length()][s2.length()];
    }

正如之前的dp题一样,这一题可以将空间化为一维。大家就自己根据我的代码看看怎么化简了。最近懒了,懒得再写一个一维的代码了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值