1. 程式人生 > 實用技巧 >LeetCode 97. 交錯字串

LeetCode 97. 交錯字串

題目連結

97. 交錯字串

題目分析

字串題目,一般不考慮暴力解法,因為極有可能會出現超時的情況(主要是重複搜尋次數太多
這個題很明顯的就是需要我們使用動態規劃去做,一開始我自己也懵逼了,三串的DP?難不成要一個三維狀態陣列嗎,但是仔細分析了一下好像其實並不是的。
因為我們s1的長度加s2的長度必定要等於s3的長度才有可能構成交錯字串,所以我們可以利用這裡的關係去把三位狀態陣列壓縮成二維。

  • dp[i][j]代表的是s1的第i-1個字元和s2的第j-1個字元匹配到s3的第i+j-1個字元的地方是否匹配

那麼我們把狀態定下來之後,就是找對應的轉移方程了,其轉移也是非常的容易理解,這裡要從上往下一個一個判斷,因為存在包含關係。

  • 如果s1的當前位字元和s2的字元相等,並且s1的字元等於s3的字元,那麼我們需要去判斷要使用哪一個才能使得交錯字串成立,所以dp[i][j] = dp[i-1][j] || dp[i][j-1];
  • 如果s1的字元等於s3的字元,那麼很明顯就是要s1往前挪一步,所以dp[i][j] = dp[i-1][j];
  • s2字元相等的情況和第二點一樣。

那麼我們還需要base cases,因為有可能單獨s1或者s2都能匹配s3,所以我們要單獨把另外一個字串為空串的情況拿出來分析。

總的來說這個題的狀態轉移和其他的字串匹配很相似,也很容易就寫出來了。

程式碼實現

class Solution {
    public boolean isInterleave(String s1, String s2, String s3) {
        if(s1.length() + s2.length() != s3.length()){
            return false;
        }
        boolean[][] dp = new boolean[s1.length()+1][s2.length()+1];
        dp[0][0] = true;
        for(int i = 0; i < s1.length(); i++){
            if(s1.charAt(i) == s3.charAt(i)){
                dp[i+1][0] = dp[i][0];
            }
        }
        for(int i = 0; i < s2.length(); i++){
            if(s2.charAt(i) == s3.charAt(i)){
                dp[0][i+1] =  dp[0][i];
            }
        }
        for(int i = 1; i < dp.length; i++){
            for(int j = 1; j < dp[i].length; j++){
                if(s1.charAt(i-1) == s2.charAt(j-1) &&  s1.charAt(i-1) == s3.charAt(i+j-1)){
                    dp[i][j] = dp[i-1][j] || dp[i][j-1];
                }else if(s1.charAt(i-1) == s3.charAt(i+j-1)){
                    dp[i][j] = dp[i-1][j];
                }else if(s2.charAt(j-1) == s3.charAt(i+j-1)){
                    dp[i][j] = dp[i][j-1];
                }
            }
        }
        return dp[dp.length-1][dp[0].length-1];
    }
}

總結

DP還是得靠自己慢慢摸索才能提升。