[Swift]LeetCode648. 单词替换 | Replace Words
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/10485210.html
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
In English, we have a concept called root
, which can be followed by some other words to form another longer word - let's call this word successor
. For example, the root an
, followed by other
, which can form another word another
.
Now, given a dictionary consisting of many roots and a sentence. You need to replace all the successor
in the sentence with the root
forming it. If a successor
has many roots
can form it, replace it with the root with the shortest length.
You need to output the sentence after the replacement.
Example 1:
Input: dict = ["cat", "bat", "rat"] sentence = "the cattle was rattled by the battery" Output: "the cat was rat by the bat"
Note:
- The input will only have lower-case letters.
- 1 <= dict words number <= 1000
- 1 <= sentence words number <= 1000
- 1 <= root length <= 100
- 1 <= sentence words length <= 1000
在英语中,我们有一个叫做 词根
(root)的概念,它可以跟着其他一些词组成另一个较长的单词——我们称这个词为 继承词
(successor)。例如,词根an
,跟随着单词 other
(其他),可以形成新的单词 another
(另一个)。
现在,给定一个由许多词根组成的词典和一个句子。你需要将句子中的所有继承词
用词根
替换掉。如果继承词
有许多可以形成它的词根
,则用最短的词根替换它。
你需要输出替换之后的句子。
示例 1:
输入: dict(词典) = ["cat", "bat", "rat"] sentence(句子) = "the cattle was rattled by the battery" 输出: "the cat was rat by the bat"
注:
- 输入只包含小写字母。
- 1 <= 字典单词数 <=1000
- 1 <= 句中词语数 <= 1000
- 1 <= 词根长度 <= 100
- 1 <= 句中词语长度 <= 1000
448ms
1 class Solution { 2 3 private let trie = Trie() 4 5 func replaceWords(_ dict: [String], _ sentence: String) -> String { 6 dict.forEach { word in 7 trie.insert(word) 8 } 9 10 var words = [String]() 11 sentence.split(separator: " ").forEach { word in 12 words.append(trie.replacement(String(word))) 13 } 14 return words.joined(separator: " ") 15 } 16 } 17 18 class Trie { 19 20 private let root = TrieNode() 21 22 func insert(_ word: String) { 23 var node = root 24 word.forEach { c in 25 let next = node.insert(c) 26 node = next 27 } 28 node.len = word.count 29 } 30 31 func replacement(_ word: String) -> String { 32 var replace = "" 33 var node = root 34 for c in word { 35 guard let next = node.search(c) else { 36 break 37 } 38 replace += String(c) 39 if next.len > 0 { 40 return replace 41 } 42 node = next 43 } 44 return word 45 } 46 } 47 48 class TrieNode { 49 50 var len = 0 51 private var map = [Character: TrieNode]() 52 53 func search(_ c: Character) -> TrieNode? { 54 return map[c] 55 } 56 57 func insert(_ c: Character) -> TrieNode { 58 if let node = map[c] { 59 return node 60 } 61 let node = TrieNode() 62 map[c] = node 63 return node 64 } 65 }
532ms
1 class Solution { 2 func replaceWords(_ dict: [String], _ sentence: String) -> String { 3 var trie = Trie() 4 5 for word in dict { 6 trie.insert(word) 7 } 8 9 var arr = sentence.split(separator: Character(" ")) 10 var res = [String]() 11 for word in arr { 12 res.append(trie.searchForAbbr(String(word))) 13 } 14 return res.joined(separator: " ") 15 } 16 } 17 18 class Trie { 19 class TrieNode: CustomStringConvertible { 20 var description: String { 21 return "\(char) children: \(children.keys)" 22 } 23 24 var char: Character = Character(" ") 25 var isWordEnding: Bool = false 26 var children: [Character: TrieNode] = [Character: TrieNode]() 27 28 init(char: Character = " ", isWordEnding: Bool = false, children: [Character: TrieNode] = [:]) { 29 self.char = char 30 self.isWordEnding = isWordEnding 31 self.children = children 32 } 33 } 34 var root: TrieNode 35 /** Initialize your data structure here. */ 36 init() { 37 root = TrieNode() 38 } 39 func searchForAbbr(_ word: String) -> String { 40 var str = "" 41 var cur = root 42 for (index,c) in word.enumerated() { 43 str = str + String(c) 44 if cur.children[c] == nil { 45 return word 46 } else { 47 let next = cur.children[c]! 48 if(next.isWordEnding) { 49 return str 50 } 51 cur = next 52 } 53 } 54 return word 55 } 56 /** Inserts a word into the trie. */ 57 func insert(_ word: String) { 58 var cur = root 59 for (index, c) in word.enumerated() { 60 if cur.children[c] == nil { 61 cur.children[c] = TrieNode(char: c, isWordEnding: index == word.count - 1 , children: [:]) 62 } else { 63 if index == word.count - 1 { 64 cur.children[c]!.isWordEnding = true 65 } 66 } 67 cur = cur.children[c]! 68 } 69 } 70 71 /** Returns if the word is in the trie. */ 72 func search(_ word: String) -> TrieNode? { 73 var cur = root 74 75 for c in word { 76 if cur.children[c] == nil { 77 return nil 78 } else { 79 let next = cur.children[c]! 80 cur = next 81 } 82 } 83 return cur 84 } 85 86 /** Returns if there is any word in the trie that starts with the given prefix. */ 87 func startsWith(_ prefix: String) -> Bool { 88 var cur = root 89 for c in prefix { 90 if cur.children[c] == nil { 91 return false 92 } 93 cur = cur.children[c]! 94 } 95 return true 96 } 97 }
544ms
1 class Solution { 2 class TrieNode { 3 var terminal = false 4 var children = [Character: TrieNode]() 5 } 6 7 class Trie { 8 var root = TrieNode() 9 10 func addWord(_ word: String) { 11 var n = root 12 for ch in word.characters { 13 if let child = n.children[ch] { 14 n = child 15 } else { 16 let newNode = TrieNode() 17 n.children[ch] = newNode 18 n = newNode 19 } 20 } 21 n.terminal = true 22 } 23 24 func getWordRoot(_ word: String) -> String { 25 var n = root 26 let arr = Array(word.characters) 27 for i in 0..<arr.count { 28 guard let child = n.children[arr[i]] else { return word } 29 n = child 30 if n.terminal { 31 return String(arr[...i]) 32 } 33 } 34 return word 35 } 36 } 37 38 func replaceWords(_ dict: [String], _ sentence: String) -> String { 39 let trie = Trie() 40 dict.forEach{ trie.addWord($0) } 41 42 let words = Array(sentence.components(separatedBy: " ")) 43 return words.map{ trie.getWordRoot($0) }.joined(separator: " ") 44 } 45 }
1 class Solution { 2 func replaceWords(_ dict: [String], _ sentence: String) -> String { 3 var dict = dict 4 var res:String = String() 5 var t:String = String() 6 var v:[[String]] = [[String]](repeating:[String](),count:26) 7 var arr:[String] = sentence.components(separatedBy:" ") 8 dict = dict.sorted { $0.count < $1.count } 9 for word in dict 10 { 11 v[word[0].ascii - 97].append(word) 12 } 13 for str in arr 14 { 15 t = str 16 for word in v[t[0].ascii - 97] 17 { 18 if t.subString(0, word.count) == word 19 { 20 t = word 21 break 22 } 23 } 24 res += t + " " 25 } 26 res.removeLast() 27 return res 28 } 29 } 30 31 //String扩展 32 extension String { 33 //subscript函数可以检索数组中的值 34 //直接按照索引方式截取指定索引的字符 35 subscript (_ i: Int) -> Character { 36 //读取字符 37 get {return self[index(startIndex, offsetBy: i)]} 38 } 39 40 // 截取字符串:指定索引和字符数 41 // - begin: 开始截取处索引 42 // - count: 截取的字符数量 43 func subString(_ begin:Int,_ count:Int) -> String { 44 let start = self.index(self.startIndex, offsetBy: max(0, begin)) 45 let end = self.index(self.startIndex, offsetBy: min(self.count, begin + count)) 46 return String(self[start..<end]) 47 } 48 } 49 50 //Character扩展 51 extension Character 52 { 53 //Character转ASCII整数值(定义小写为整数值) 54 var ascii: Int { 55 get { 56 return Int(self.unicodeScalars.first?.value ?? 0) 57 } 58 } 59 }
568ms
1 class Solution { 2 class Node { 3 var value: Character? 4 var children: [Character : Node] = [:] 5 var isTerminating = false 6 7 init(value: Character? = nil) { 8 self.value = value 9 } 10 11 func add(_ letter: Character) { 12 guard children[letter] == nil else { return } 13 children[letter] = Node(value: letter) 14 } 15 } 16 17 var root = Node() 18 19 func addWord(_ word: String) { 20 guard !word.isEmpty else { return } 21 22 var currentNode = root 23 24 for letter in word { 25 if currentNode.children[letter] == nil { 26 currentNode.add(letter) 27 } 28 29 guard let node = currentNode.children[letter] else { continue } 30 currentNode = node 31 } 32 33 currentNode.isTerminating = true 34 } 35 36 func findRoot(_ word: String) -> String? { 37 var result = "" 38 var currentNode = root 39 40 for letter in word { 41 if let node = currentNode.children[letter] { 42 currentNode = node 43 if let value = node.value { 44 result += String(value) 45 } 46 47 if currentNode.isTerminating { 48 return result 49 } 50 } else { 51 if currentNode.isTerminating { 52 return result 53 } else { 54 return nil 55 } 56 } 57 } 58 59 return result.isEmpty ? nil : result 60 } 61 62 func replaceWords(_ dict: [String], _ sentence: String) -> String { 63 var result = "" 64 65 for word in dict { 66 addWord(word) 67 } 68 69 var currentWord = "" 70 71 for char in sentence { 72 if char == " " { 73 result += (findRoot(currentWord) ?? currentWord) + " " 74 currentWord = "" 75 } else { 76 currentWord += String(char) 77 } 78 } 79 80 result += findRoot(currentWord) ?? currentWord 81 return result 82 } 83 }
632ms
1 class Solution { 2 class TrieNode<Key : Hashable>{ 3 public var key : Key? 4 public var isTerminating : Bool = false 5 public var children : [Key : TrieNode] = [:] 6 public init(_ key : Key?){ 7 self.key = key 8 } 9 } 10 11 func replaceWords(_ dict: [String], _ sentence: String) -> String { 12 let trie = Trie<String>.init() 13 for str in dict{ 14 trie.insert(str) 15 } 16 var results : [String] = [] 17 let components = sentence.components(separatedBy: " ") 18 for component in components{ 19 if let replacement = trie.findPrefixesWithCollection(component, prefix: ""){ 20 results.append(replacement) 21 }else{ 22 results.append(component) 23 } 24 } 25 26 return results.joined(separator: " ") 27 } 28 29 class Trie<CollectionType : RangeReplaceableCollection> where CollectionType.Element : Hashable{ 30 public typealias Node = TrieNode<CollectionType.Element> 31 private let root = Node.init(nil) 32 public init(){} 33 34 // Insertion 35 public func insert(_ collection : CollectionType){ 36 var current = root 37 for element in collection{ 38 if current.children[element] == nil{ 39 current.children[element] = Node.init(element) 40 } 41 current = current.children[element]! 42 } 43 current.isTerminating = true 44 } 45 46 public func findPrefixesWithCollection(_ collection : CollectionType, prefix : CollectionType)->CollectionType?{ 47 var current = root 48 var result = prefix 49 50 for element in collection{ 51 if current.isTerminating == true{ 52 break 53 }else{ 54 if current.children[element] == nil{ 55 return nil 56 }else{ 57 result.append(element) 58 current = current.children[element]! 59 } 60 } 61 } 62 // now we have gotten the shortest word 63 return result 64 } 65 } 66 }
692ms
1 class Solution { 2 func replaceWords(_ dict: [String], _ sentence: String) -> String { 3 let trie = Trie() 4 for root in dict { 5 trie.insert(root) 6 } 7 8 var retval: [String] = [] 9 let words = sentence.components(separatedBy: " ") 10 for word in words { 11 retval.append(trie.startsWith(word) ?? word) 12 } 13 return retval.joined(separator: " ") 14 } 15 } 16 17 18 19 class TrieNode { 20 var key: Character? 21 var children: [Character: TrieNode] = [:] 22 var isTerminator = false 23 24 init() { 25 } 26 27 init(_ key: Character) { 28 self.key = key 29 } 30 } 31 32 33 class Trie { 34 private let root: TrieNode 35 /** Initialize your data structure here. */ 36 init() { 37 root = TrieNode() 38 } 39 40 /** Inserts a word into the trie. */ 41 func insert(_ word: String) { 42 var node = root 43 for char in word { 44 if let some = node.children[char] { 45 node = some 46 } else { 47 let n = TrieNode(char) 48 node.children[char] = n 49 node = n 50 } 51 } 52 node.isTerminator = true 53 } 54 55 /** Returns if there is any word in the trie that starts with the given prefix. */ 56 func startsWith(_ prefix: String) -> String? { 57 var retVal = "" 58 var node = root 59 for char in prefix { 60 if let some = node.children[char] { 61 node = some 62 retVal.append(node.key!) 63 if node.isTerminator { 64 return retVal 65 } 66 } else { 67 return nil 68 } 69 } 70 return retVal 71 } 72 }