[Swift]LeetCode87. 扰乱字符串 | Scramble String
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/9935700.html
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
Given a string s1, we may represent it as a binary tree by partitioning it to two non-empty substrings recursively.
Below is one possible representation of s1 = "great"
:
great / \ gr eat / \ / \ g r e at / \ a t
To scramble the string, we may choose any non-leaf node and swap its two children.
For example, if we choose the node "gr"
and swap its two children, it produces a scrambled string "rgeat"
.
rgeat / \ rg eat / \ / \ r g e at / \ a t
We say that "rgeat"
is a scrambled string of "great"
.
Similarly, if we continue to swap the children of nodes "eat"
and "at"
, it produces a scrambled string "rgtae"
.
rgtae / \ rg tae / \ / \ r g ta e / \ t a
We say that "rgtae"
is a scrambled string of "great"
.
Given two strings s1 and s2 of the same length, determine if s2 is a scrambled string of s1.
Example 1:
Input: s1 = "great", s2 = "rgeat" Output: true
Example 2:
Input: s1 = "abcde", s2 = "caebd" Output: false
给定一个字符串 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
56ms
1 class Solution { 2 func isScramble(_ s1: String, _ s2: String) -> Bool { 3 if s1 == s2 { 4 return true 5 } 6 7 var letters = [Int](repeating: 0, count: 26) 8 9 for i in 0..<s1.count { 10 let aASCII = Character("a").ascii 11 letters[s1[i].ascii - aASCII] += 1 12 letters[s2[i].ascii - aASCII] -= 1 13 } 14 for i in 0..<26 { 15 if letters[i] != 0 { 16 return false 17 } 18 } 19 for i in 1..<s1.count { 20 if isScramble(s1[0..<i], s2[0..<i]) && 21 isScramble(s1[i..<s1.count], s2[i..<s2.count]) { 22 return true 23 } 24 if isScramble(s1[0..<i], s2[(s2.count - i)..<s2.count]) && 25 isScramble(s1[i..<s1.count], s2[0..<(s2.count - i)]) { 26 return true 27 } 28 } 29 30 return false 31 } 32 } 33 34 extension String { 35 subscript (i: Int) -> Character { 36 return self[index(startIndex, offsetBy: i)] 37 } 38 39 subscript(_ range: CountableRange<Int>) -> String { 40 let idx1 = index(startIndex, offsetBy: max(0, range.lowerBound)) 41 let idx2 = index(startIndex, offsetBy: min(self.count, range.upperBound)) 42 return String(self[idx1..<idx2]) 43 } 44 } 45 46 extension Character { 47 var ascii: Int { 48 get { 49 let s = String(self).unicodeScalars 50 return Int(s[s.startIndex].value) 51 } 52 } 53 54 func isDigit() -> Bool { 55 return self >= "0" && self <= "9" 56 } 57 }
56ms
1 class Solution { 2 func isScramble(_ s1: String, _ s2: String) -> Bool { 3 return isScramble_recursion(s1: s1, s2: s2) 4 } 5 6 func isScramble_recursion(s1: String?, s2: String?) -> Bool { 7 if s1 == nil || s2 == nil || s1?.count != s2?.count { 8 return false 9 } 10 if s1 == s2 { 11 return true 12 } 13 if (s1?.sorted())! != (s2?.sorted())! { 14 return false 15 } 16 let count: Int = (s1?.count)! 17 for i in 1 ..< count { 18 if isScramble_recursion(s1: s1![0..<i], s2: s2![0..<i]) && isScramble_recursion(s1: s1![i..<Int.max], s2: s2![i..<Int.max]) { 19 return true 20 } 21 if isScramble_recursion(s1: s1![0..<i], s2: s2![(s2?.count)! - i..<Int.max]) && isScramble_recursion(s1: s1![i..<Int.max], s2: s2![0..<(s2?.count)! - i]) { 22 return true 23 } 24 } 25 return false 26 } 27 static func isScramble_iteration(s1: String?, s2: String?) -> Bool { 28 if s1 == nil || s2 == nil || s1?.count != s2?.count { 29 return false 30 } 31 let len = s1?.count 32 var dp: Array<Array<Array<Bool>>> = Array<Array<Array<Bool>>>(repeating: Array<Array<Bool>>(repeating: Array<Bool>(repeating: false, count: 100), count: 100), count: 100) 33 for i in (0...len! - 1).reversed() { 34 for j in (0...len!-1).reversed() { 35 dp[i][j][1] = (s1![i] == s2![j]) 36 var l = 2 37 while i + l <= len! && j + l <= len! { 38 for n in 1 ..< l { 39 dp[i][j][l] = dp[i][j][l] || ( dp[i][j][n] && dp[i+n][j+n][l-n] ) 40 dp[i][j][l] = dp[i][j][l] || ( dp[i][j+l-n][n] && dp[i+n][j][l-n] ) 41 } 42 l += 1 43 } 44 } 45 } 46 return dp[0][0][len!] 47 } 48 } 49 private extension String { 50 subscript (range: Range<Int>) -> String { 51 guard let localEndIndex = self.index(self.startIndex, offsetBy: range.upperBound, limitedBy: self.endIndex) else { 52 return String(self[self.index(self.startIndex, offsetBy: range.lowerBound)..<self.endIndex]) 53 } 54 return String(self[self.index(self.startIndex, offsetBy: range.lowerBound)..<localEndIndex]) 55 } 56 subscript (index: Int) -> Character { 57 return self[self.index(self.startIndex, offsetBy: index)] 58 } 59 }
180ms
1 class Solution { 2 3 func isScramble(_ s1: String, _ s2: String) -> Bool { 4 guard s1.count == s2.count else { return false } 5 guard s1.count > 0 else { return false } 6 7 var dp = [[[Bool]]](repeating: [[Bool]](repeating: [Bool](repeating: false, count: s1.count + 1), count: s1.count), count: s1.count) 8 9 for i in 0..<s1.count { 10 for j in 0..<s2.count { 11 dp[i][j][1] = s1.charAt(i) == s2.charAt(j) 12 } 13 } 14 15 if s1.count > 1 { 16 for len in 2...s1.count { 17 for i in 0...s1.count - len { 18 for j in 0...s2.count - len { 19 for w in 1..<len { 20 if dp[i][j][w] && dp[i + w][j + w][len - w] { 21 dp[i][j][len] = true 22 break 23 } 24 if dp[i][j + len - w][w] && dp[i + w][j][len - w] { 25 dp[i][j][len] = true 26 break 27 } 28 } 29 } 30 } 31 } 32 } 33 34 return dp[0][0][s1.count] 35 } 36 } 37 38 extension String { 39 40 func charAt(_ i: Int) -> Character { 41 let index = self.index(self.startIndex, offsetBy: i) 42 return self[index] 43 } 44 }