Medium草稿★★★★★O(m * n) 時間 · O(n) 空間
Dynamic ProgrammingString
Patterns🔲 網格・雙序列 DP
尚未複習過

解法已隱藏 — 先讀題目敘述、自己想想看,再點上方按鈕揭曉。

97Interleaving String2-D DPMedium2-D DP

給定三個字串 s1s2s3,判斷 s3 是否由 s1s2 交錯組成。交錯是指將 s1s2 各自分割後交替拼接(保持原有順序)能形成 s3

Example:

Input: s1 = “aabcc”, s2 = “dbbca”, s3 = “aadbbcbcac” Output: true

Intuition

TIP

dp[i][j] 表示 s1 前 i 個字元和 s2 前 j 個字元能否交錯組成 s3 的前 i+j 個字元。

Approaches

1. 2D DP Table — O(m * n) / O(m * n)
  • Idea: 建立 (m+1) x (n+1) 的布林表格,逐格填寫。
  • Time: O(m * n)
  • Space: O(m * n)
class Solution {
    fun isInterleave(s1: String, s2: String, s3: String): Boolean {
        val m = s1.length
        val n = s2.length
        if (m + n != s3.length) return false
        val dp = Array(m + 1) { BooleanArray(n + 1) }
        dp[0][0] = true
        for (i in 1..m) dp[i][0] = dp[i - 1][0] && s1[i - 1] == s3[i - 1]
        for (j in 1..n) dp[0][j] = dp[0][j - 1] && s2[j - 1] == s3[j - 1]
        for (i in 1..m) {
            for (j in 1..n) {
                dp[i][j] = (dp[i - 1][j] && s1[i - 1] == s3[i + j - 1]) ||
                            (dp[i][j - 1] && s2[j - 1] == s3[i + j - 1])
            }
        }
        return dp[m][n]
    }
}
⭐ 2. 1D DP (Space Optimized) — O(m * n) / O(n)
  • Idea: 只保留一行,逐行更新。dp[j] 保留上一行的值。
  • Time: O(m * n)
  • Space: O(n)
class Solution {
    fun isInterleave(s1: String, s2: String, s3: String): Boolean {
        val m = s1.length
        val n = s2.length
        if (m + n != s3.length) return false
        val dp = BooleanArray(n + 1)
        for (i in 0..m) {
            for (j in 0..n) {
                if (i == 0 && j == 0) {
                    dp[j] = true
                } else if (i == 0) {
                    dp[j] = dp[j - 1] && s2[j - 1] == s3[j - 1]
                } else if (j == 0) {
                    dp[j] = dp[j] && s1[i - 1] == s3[i - 1]
                } else {
                    dp[j] = (dp[j] && s1[i - 1] == s3[i + j - 1]) ||
                            (dp[j - 1] && s2[j - 1] == s3[i + j - 1])
                }
            }
        }
        return dp[n]
    }
}

🔑 Takeaways