leetcode:交错字符串

https://leetcode-cn.com/problems/interleaving-string/

DFS:

可能大家想的第一种方法就是挨个挨个的去比较,设置三个指针,i,j,k,如果s1的第一个元素和s3的第一个元素相等,则i和k都要后移一位,就这样比较下去,直到 所有指针都到达最后,就说明是交错字符串。但是有个很坑的地方,如果s1和s2指针所指的元素都和s3的目标元素相同,那么这时候面临两种选择,但是这样就会得出错误的答案。样例1的那个就会出错。

但是,我们还是想要用那种办法,我就可以用深搜,分别去递归两种情况,如果不成功,就回溯过来,选择另一种方式。

class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
        return f(s1, 0, s2, 0, s3, 0);
    }
    //i,j,k分别指向s1,s2和s3的指针.
    private boolean f(String s1, int i, String s2, int j, String s3, int k){
        if(s1.length() + s2.length() != s3.length())
            return false;
        if(i == s1.length() && j == s2.length() && k == s3.length())//成功,退出
            return true;
        if(i == s1.length()){//s1或者s2其中一个遍历完了,就只需要遍历另一个就行了
            while (j < s2.length()){
                if(s2.charAt(j) != s3.charAt(k))
                    return false;
                j++;
                k++;
            }
            return true;
        }
        if(j == s2.length()){
            while (i < s1.length()){
                if(s1.charAt(i) != s3.charAt(k))
                    return false;
                i++;
                k++;
            }
            return true;
        }
        //碰到相同的情况,两种情况都试一下
        if(s1.charAt(i) == s3.charAt(k)){
            if(f(s1, i + 1, s2, j, s3, k + 1))
                return true;
        }
        if(s2.charAt(j) == s3.charAt(k)){
            if(f(s1, i, s2, j + 1, s3, k + 1))
                return true;
        }
        return false;
    }
}

动态规划:

利用动态规划的思想,s1的前i个元素和s2的前j个元素,能否组成s3的前i+j个元素,取决于s1的前i-1个元素和s2的前j个元素,能否组成s3的前i+j-1个元素,并且s1的第i个元素等于s3的第i+j个元素。同理s2的前j-1个元素也一样。

设一个二维数组dp[i][j]表示s1的前i个元素和s2的前j个元素,能否组成s3的前i+j个元素。

状态转移方程:dp[i][j] = (dp[i - 1][j] && s3(i + j - 1) = s1(i - 1)) || (dp[i][j - 1] && s3(i + j - 1) = s2(j - 1));

class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
        int l1 = s1.length(),l2 = s2.length(),l3 = s3.length();
        if(l1 + l2 != l3) return false;
        boolean[][] dp = new boolean[l1+1][l2+1];
        dp[0][0] = true;
        //i或者j为0的时候单独考虑
        for (int i = 1; i <= l1; i++) {
            if(s1.charAt(i - 1) == s3.charAt(i - 1)) dp[i][0] = dp[i-1][0];
        }
        for (int i = 1; i <= l2 ; i++) {
            if(s2.charAt(i - 1) == s3.charAt(i - 1)) dp[0][i] = dp[0][i-1];
        }
        for (int i = 1; i <= l1; i++) {
            for (int j = 1; j <=l2 ; j++) {
                dp[i][j] = (dp[i - 1][j] && s3.charAt(i + j - 1) == s1.charAt(i - 1))
                        || (dp[i][j - 1] && s3.charAt(i + j - 1) == s2.charAt(j - 1));
            }
        }
        return dp[l1][l2];
    }
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值