1. 程式人生 > >[Swift]LeetCode676. 實現一個魔法字典 | Implement Magic Dictionary

[Swift]LeetCode676. 實現一個魔法字典 | Implement Magic Dictionary

oss self ets private direct 變量 init 一個 字母

Implement a magic directory with buildDict, and search methods.

For the method buildDict, you‘ll be given a list of non-repetitive words to build a dictionary.

For the method search, you‘ll be given a word, and judge whether if you modify exactly one character into another character in this word, the modified word is in the dictionary you just built.

Example 1:

Input: buildDict(["hello", "leetcode"]), Output: Null
Input: search("hello"), Output: False
Input: search("hhllo"), Output: True
Input: search("hell"), Output: False
Input: search("leetcoded"), Output: False 

Note:

  1. You may assume that all the inputs are consist of lowercase letters a-z
    .
  2. For contest purpose, the test data is rather small by now. You could think about highly efficient algorithm after the contest.
  3. Please remember to RESET your class variables declared in class MagicDictionary, as static/class variables are persisted across multiple test cases. Please see herefor more details.

實現一個帶有buildDict, 以及 search方法的魔法字典。

對於buildDict方法,你將被給定一串不重復的單詞來構建一個字典。

對於search方法,你將被給定一個單詞,並且判定能否只將這個單詞中一個字母換成另一個字母,使得所形成的新單詞存在於你構建的字典中。

示例 1:

Input: buildDict(["hello", "leetcode"]), Output: Null
Input: search("hello"), Output: False
Input: search("hhllo"), Output: True
Input: search("hell"), Output: False
Input: search("leetcoded"), Output: False

註意:

  1. 你可以假設所有輸入都是小寫字母 a-z
  2. 為了便於競賽,測試所用的數據量很小。你可以在競賽結束後,考慮更高效的算法。
  3. 請記住重置MagicDictionary類中聲明的類變量,因為靜態/類變量會在多個測試用例中保留。 請參閱這裏了解更多詳情。

8ms

 1 class MagicDictionary {
 2     var map = [Int: Set<String>]()
 3     /** Initialize your data structure here. */
 4     init() {
 5 
 6     }
 7 
 8     /** Build a dictionary through a list of words */
 9     func buildDict(_ dict: [String]) {
10         map.removeAll()
11         for str in dict {
12             var sets = map[str.count, default: Set<String>()]
13             sets.insert(str)
14             map[str.count] = sets
15         }
16     }
17 
18     /** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */
19     func search(_ word: String) -> Bool {
20         let sets = map[word.count, default: Set<String>()]
21         let srcChars = Array(word)
22         for str in sets {
23             var diffct = 0
24             let curChars = Array(str)
25             for i in 0..<word.count {
26                 if srcChars[i] != curChars[i] { diffct += 1 }
27                 if diffct > 1 { break }
28             }
29             if diffct == 1 { return true }
30         }
31         return false
32     }
33 }
34 
35 /**
36  * Your MagicDictionary object will be instantiated and called as such:
37  * let obj = MagicDictionary()
38  * obj.buildDict(dict)
39  * let ret_2: Bool = obj.search(word)
40  */

16ms

 1 class MagicDictionary {
 2     private var dictionary : [Int : [String]] = [:]
 3     /** Initialize your data structure here. */
 4     init() {
 5         
 6     }
 7     
 8     /** Build a dictionary through a list of words */
 9     func buildDict(_ dict: [String]) {
10         for str in dict{
11             if dictionary[str.count] == nil{
12                 dictionary[str.count] = [str]
13             }else{
14                 dictionary[str.count]!.append(str)
15             }
16             
17         }
18     }
19     
20     /** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */
21     func search(_ word: String) -> Bool {
22         guard let words = dictionary[word.count] else{
23             return false
24         }
25         
26         for str in words{
27             if isOneDifference(Array(str), Array(word)){
28                 return true
29             }
30         }
31         return false
32     }
33     
34     private func isOneDifference(_ first : [Character], _ second : [Character])->Bool{
35         guard first.count == second.count else{
36             return false
37         }
38         var movingIndex : Int = 0
39         var diffCount : Int = 0
40         
41         while movingIndex < first.count{
42             if first[movingIndex] != second[movingIndex]{
43                 if diffCount == 1{
44                     return false
45                 }
46                 diffCount += 1
47             }
48             movingIndex += 1
49         }
50         
51         return diffCount == 1
52     }
53 }

20ms

  1 class MagicDictionary {
  2 
  3     
  4     var trie: Trie
  5     
  6     /** Initialize your data structure here. */
  7     init() {
  8         self.trie = Trie()
  9     }
 10     
 11     /** Build a dictionary through a list of words */
 12     func buildDict(_ dict: [String]) {
 13         dict.forEach{ self.trie.insert($0) }
 14 
 15     }
 16     
 17     /** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */
 18     func search(_ word: String) -> Bool {
 19       
 20         let wordArray = word.map{ String($0) }
 21                 
 22         return self.trie.search(wordArray, errorCount: 0)        
 23     }    
 24 }
 25 
 26 class Trie {
 27     
 28     var roots: [String: Node]
 29     
 30     init() {
 31         self.roots = [String: Node]()
 32     }
 33     
 34     func search(_ word: [String], errorCount: Int) -> Bool {
 35         
 36         guard let first = word.first else { return false }
 37         
 38         var result = false        
 39         self.roots.forEach{ (key, value) in
 40                           
 41                            let newResult = search(word, at: value, errorCount: errorCount)
 42                            result = result || newResult
 43                            
 44                           }
 45         
 46         return result
 47     }
 48     
 49     func search(_ word: [String], at node: Node, errorCount: Int) -> Bool {
 50         
 51         guard let first = word.first else { return errorCount == 1 }
 52         
 53         if first != node.char && errorCount >= 1 { return false }
 54         
 55         var errorCount = errorCount
 56         if first != node.char { errorCount += 1 }
 57         
 58         if word.count == 1 && errorCount == 1 && node.isWord { return true }
 59         
 60         var newWord = word
 61         newWord.removeFirst()
 62         
 63         if let next = newWord.first {            
 64             let allChilds = node.childs
 65             var result = false
 66             allChilds.forEach{ (key, value) in
 67                               let newResult = search(newWord, at: value, errorCount: errorCount)
 68                               result = result || newResult
 69                 }
 70                 
 71                 return result
 72         }        
 73         return false        
 74     } 
 75     
 76     
 77     func insert(_ word: String) {        
 78         var wordArray = word.map{ String($0) }        
 79         guard let first = wordArray.first else { return }
 80         var node = self.roots[first] ?? Node(first)   
 81         self.roots[first] = insert(wordArray, at: node)        
 82     }
 83     
 84     
 85     func insert(_ word: [String], at node: Node) -> Node {
 86         
 87         guard let first = word.first else { return node }
 88         guard first == node.char else { return node }
 89 
 90         if word.count == 1 {
 91             node.isWord = true
 92             return node
 93         }
 94         
 95         var newWord = word
 96         newWord.removeFirst()
 97         
 98         let next = newWord.first!
 99                 
100         let child = node.childs[next] ?? Node(next) 
101         
102         let newChild = insert(newWord, at: child)
103         
104         node.childs[next] = newChild
105         
106         return node
107     }
108     
109 }
110 
111 class Node {
112     
113     let char: String
114     var isWord = false
115     var childs: [String: Node]
116     
117     init(_ char: String) {
118         
119         self.char = char
120         self.childs = [String: Node]()
121     }    
122 }

Runtime: 72 ms Memory Usage: 20 MB
 1 class MagicDictionary {
 2     var s:Set<String>
 3 
 4     /** Initialize your data structure here. */
 5     init() {
 6         s = Set<String>()
 7     }
 8     
 9     /** Build a dictionary through a list of words */
10     func buildDict(_ dict: [String]) {
11         for word in dict
12         {
13             s.insert(word)
14         }      
15     }
16     
17     /** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */
18     func search(_ word: String) -> Bool {  
19         var word = word
20         var arr:[Character] = Array(word)
21         for i in 0..<arr.count
22         {
23             var t:Character = arr[i]
24             for c in 97...122
25             {
26                 var char = c.ASCII
27                 if char == t {continue}
28                 arr[i] = char
29                 word = String(arr)
30                 if s.contains(word)
31                 {
32                     return true
33                 }
34             }          
35             arr[i] = t
36         }
37         return false      
38     }
39 }
40 
41 //Int擴展
42 extension Int
43 {
44     //Int轉Character,ASCII值(定義大寫為字符值)
45     var ASCII:Character 
46     {
47         get {return Character(UnicodeScalar(self)!)}
48     }
49 }
50 /**
51  * Your MagicDictionary object will be instantiated and called as such:
52  * let obj = MagicDictionary()
53  * obj.buildDict(dict)
54  * let ret_2: Bool = obj.search(word)
55  */
56  

[Swift]LeetCode676. 實現一個魔法字典 | Implement Magic Dictionary