LeetCode 97 - Interleaving String
題目
題目連結:https://leetcode.com/problems/interleaving-string/
給定字串 s1, s2 以及 s3,問是否能將 s1, s2 交織(interleaving) 而成 s3。
若字串兩字串 s, t,其中 s = s1 + s2 + ... + sn, t = t1 + t2 + ... + tm 且 |n - m| < 1,
則 s, t 的交織 (interleaving) 可以是 s1 + t1 + s2 + t2 + ... 或是 t1 + s1 + t2 + s2 + ...。
範例說明
Example 1:

1  | Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbcbcac"  | 
Example 2:
1  | Input: s1 = "aabcc", s2 = "dbbca", s3 = "aadbbbaccc"  | 
Example 3:
1  | Input: s1 = "", s2 = "", s3 = ""  | 
想法
題目對於交織的說明容易誤導思考的方向,其實不用在乎要先將字串的切斷再輪流加入、連接起來。可以直接想成是兩個字串隨機的順序將字元放入新的字串就好。
假設 s1, s2 兩字串的索引從 1 開始。
定義 dp(i, j) 代表 s1[1 ~ i], s2[1 ~ j] 兩個子字串可以交織而成 s3[1, i + j]。
則 dp(i, j) = true 當:
s1[1 ~ i - 1],s2[1 ~ j]可以交織而成s3[i + j - 1],且s1[i] == s3[i + j]。即dp(i - 1, j) == true && s1[i] == s3[i + j]。s1[1 ~ i],s2[1 ~ j - 1]可以交織而成s3[i + j - 1],且s2[j] == s3[i + j]。即dp(i, j - 1) == true && s2[j] == s3[i + j]。
注意 dp(0, 0) = true,因為兩個空字串可以交織而成空字串。
實作細節
實作時,因為 s1, s2, s3 都是從 0 開始索引的,因此在使用到 s1, s2, s3 的時候都要多減一。
也要注意到轉移 1 是從 dp(i - 1, j) 轉移到 dp(i, j),因此只有在 i > 0 時才能轉移;同理轉移 2 則只能在 j > 0 時轉移。
可以發現,轉移式中,dp(i - 1, j) 只會從 dp(i - 1, j) 以及 dp(i, j - 1) 轉移,因此其實可以不用 N * M 大小的陣列來記錄。
使用一個一維的 dp(j) 代表 dp(i, j),並且迴圈外層 i 從 0 ~ N,內層 j 從 0 ~ M,當要從 dp(i - 1, j) 轉移時,dp(j) 即為 dp(i - 1, j),所以即是從 dp(j) 轉移到 dp(j);當要從 dp(i, j - 1) 轉移時,即為從 dp(j - 1) 轉移到 dp(j)。
注意迴圈的順序是不能改變的,轉移才不會錯誤。
程式碼
Space O(NM)
1  | /**  | 
Space O(min(N, M))
1  | /**  |