【leetcode-97 動態規劃】 交錯字符串

(1過,調試好久)spa

給定三個字符串 s1s2s3, 驗證 s3 是不是由 s1 和 s2 交錯組成的。調試

示例 1:code

輸入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"
輸出: true

示例 2:blog

輸入: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"
輸出: false

 

關鍵:設dp[i][j]表示s3的前i+j個字符能夠由s1的前i個字符和s2的前j個字符交織而成索引

看了這句提示才寫出來,中途忽略了length1 + length2 != length3的條件調試了好久字符串

    public boolean isInterleave(String s1, String s2, String s3) {
        int length1 = s1.length();
        int length2 = s2.length();
        //s3長度可能小於s1+s2,s3.charAt(i+j-1)會溢出
        int length3 = s3.length();
        //設dp[i][j]表示s3的前i+j個字符能夠由s1的前i個字符和s2的前j個字符交織而成
        boolean[][] dp = new boolean[length1+1][length2+1];
        //初始化
        if (length1 + length2 != length3)
            return false;
        dp[0][0] = true;
        for (int i=1;i<=length1;i++) {
            if (dp[i - 1][0] && s1.charAt(i-1) == s3.charAt(i-1))
                dp[i][0] = true;
            else
                dp[i][0] = false;
        }
        for (int i=1;i<=length2;i++) {
            if (dp[0][i-1] && s2.charAt(i-1) == s3.charAt(i-1))
                dp[0][i] = true;
            else
                dp[0][i] = false;
        }
        for (int i=1;i<=length1;i++) {
            for (int j=1;j<=length2;j++) {
                    if ((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))) {
                        dp[i][j] = true;
                    } else {
                        dp[i][j] = false;
                    }
            }
        }
        return dp[length1][length2];
    }

 

參考:io

s3是由s1和s2交織生成的,意味着s3由s1和s2組成,在s3中s1和s2字符的順序是不能變化的,和子序列題型相似,這種題咱們通常是用動態規劃來解。 class

    1. 設dp[i][j]表示s3的前i+j個字符能夠由s1的前i個字符和s2的前j個字符交織而成。
  1. 狀態轉移方程:有兩種狀況
    • 第一個狀態轉移方程:
      dp[i][j]= {(dp[i - 1][j] && s1.charAt(i - 1) == s3.charAt(i + j - 1)}
      dp[i-1][j]表示若s3的前i+j-1個字符可以由s1前i-1個字符和s2的前j個字符交織而成,那麼只須要s1的第i個字符與s3的第i+j個字符相等(charAt索引從0開始),那麼dp[i][j]=true;
    • 第二個狀態轉移方程:
      dp[i][j]= {(dp[i][j-1] && s2.charAt(j - 1) == s3.charAt(i + j - 1)}
      dp[i-1][j]表示若s3的前i+j-1個字符可以由s1前i個字符和s2的前j-1個字符交織而成,那麼只須要s2的第j個字符與s3的第i+j個字符相等(charAt索引從0開始),那麼dp[i][j]=true;
連接:https://www.nowcoder.com/questionTerminal/4d0f94617e454e2da23e660cded4d9e8
來源:牛客網

public class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
        int len1 = s1.length();
        int len2 = s2.length();
        int len3 = s3.length();
       
        if(len1+len2 !=len3){
          return false;
        }
         
        char[] chs1 = s1.toCharArray();
        char[] chs2 = s2.toCharArray();
        char[] chs3 = s3.toCharArray();
         
        //dp[i][j]表明 chs1[0...i]  chs2[0...j]可否順序匹配chs3[i+j]
        boolean[][] dp = new boolean[len1+1][len2+1];
        //初始化 s1中取0個字符 s2中取0個字符 匹配s3從0開始的0個字符 確定匹配true
        dp[0][0] = true;
         
        //s1中取0個s2中取i個 去和s3中0+i 個匹配
        for(int i = 1 ; i < len2 + 1; i ++ ){
          dp[0][i] = dp[0][i-1] && chs2[i-1] == chs3[i-1];
        }
        //s2中取0個s1中取i個 去和s3中0+i 個匹配
        for(int i = 1 ; i < len1 + 1; i ++ ){
          dp[i][0] = dp[i-1][0] && chs1[i-1] == chs3[i-1];
        }
         
        for(int i = 1 ; i < len1+1 ; i ++ ){
          for(int j = 1 ; j < len2+1 ; j ++ ){
            dp[i][j] = dp[i-1][j] && (chs3[i+j-1] == chs1[i-1]) 
                || dp[i][j-1] && (chs3[i+j-1] == chs2[j-1]);
          }
        }
         
        return dp[len1][len2];
    }
}
相關文章
相關標籤/搜索