leetcode刷題筆記八十七題 擾亂字串
阿新 • • 發佈:2020-07-28
leetcode刷題筆記八十七題 擾亂字串
源地址:87. 擾亂字串
問題描述:
給定一個字串 s1,我們可以把它遞迴地分割成兩個非空子字串,從而將其表示為二叉樹。
下圖是字串 s1 = "great" 的一種可能的表示形式。
great
/
gr eat
/ \ /
g r e at
/
a t
在擾亂這個字串的過程中,我們可以挑選任何一個非葉節點,然後交換它的兩個子節點。例如,如果我們挑選非葉節點 "gr" ,交換它的兩個子節點,將會產生擾亂字串 "rgeat" 。
rgeat
/
rg eat
/ \ /
r g e at
/
a t
我們將 "rgeat” 稱作 "great" 的一個擾亂字串。同樣地,如果我們繼續交換節點 "eat" 和 "at" 的子節點,將會產生另一個新的擾亂字串 "rgtae" 。
rgtae
/
rg tae
/ \ /
r g ta e
/
t a
我們將 "rgtae” 稱作 "great" 的一個擾亂字串。給出兩個長度相等的字串 s1 和 s2,判斷 s2 是否是 s1 的擾亂字串。
示例 1:
輸入: s1 = "great", s2 = "rgeat"
輸出: true
示例 2:輸入: s1 = "abcde", s2 = "caebd"
輸出: false
/** 題解參考https://leetcode-cn.com/problems/scramble-string/solution/miao-dong-de-qu-jian-xing-dpsi-lu-by-sha-yu-la-jia/ 使用區間型dp進行處理,依題意, str可被分割為str1和str2, tStr可被分割為tStr1和tStr2.滿足str1 == tStr1 且 str2 == tStr2 情況或者 str1 == tStr2 且 str2 == tStr1時,認為可返回true 使用dp(i)(j)(k)(h) 表示str(i,j) 與 tStr(k,h) 是否成立 但由於要求str.length == tStr.length,將dp陣列簡化為dp(i)(j)(len) 初始狀態 dp(i)(j)(1) == str(i) == tStr(j) 狀態轉換方程 dp(i)(j)(len) == (dp(i)(j)(k) && dp(i+k)(j+k)(len-k)) || (dp(i)(j+len-k)(k) && dp(i+k)(j)(len-k)) 時間複雜度:O(n^4) 空間複雜度:O(n^3) */ import util.control.Breaks._ object Solution { def isScramble(s1: String, s2: String): Boolean = { //要求str與tStr長度一致 val str1Length = s1.length val str2Length = s2.length if(str1Length != str2Length) return false val dp = Array.ofDim[Boolean](str1Length, str1Length, str1Length+1) for(i <- 0 to str1Length-1){ for(j <- 0 to str1Length-1){ if(s1(i) == s2(j)) dp(i)(j)(1) = true else dp(i)(j)(1) = false } } for(len <- 2 to str1Length){ for(i <- 0 to str1Length-len){ for(j <- 0 to str1Length-len){ breakable{ for(k <- 1 to len-1){ if(dp(i)(j)(k) && dp(i+k)(j+k)(len-k)){ dp(i)(j)(len) = true break() } if(dp(i)(j+len-k)(k) && dp(i+k)(j)(len-k)){ dp(i)(j)(len) = true break() } } } } } } return dp(0)(0)(str1Length) } }