[Swift]LeetCode1178. 猜字謎 | Number of Valid Words for Each Puzzle

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(www.zengqiang.org
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:http://www.javashuo.com/article/p-chlylsrc-hx.html 
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★html

With respect to a given puzzle string, a word is valid if both the following conditions are satisfied:node

  • word contains the first letter of puzzle.
  • For each letter in word, that letter is in puzzle.
    For example, if the puzzle is "abcdefg", then valid words are "faced", "cabbage", and "baggage"; while invalid words are "beefed" (doesn't include "a") and "based" (includes "s" which isn't in the puzzle).

Return an array answer, where answer[i] is the number of words in the given word list words that are valid with respect to the puzzle puzzles[i].git

 

Example :github

Input: 
words = ["aaaa","asas","able","ability","actt","actor","access"], 
puzzles = ["aboveyz","abrodyz","abslute","absoryz","actresz","gaswxyz"]
Output: [1,1,3,2,4,0]
Explanation:
1 valid word for "aboveyz" : "aaaa" 
1 valid word for "abrodyz" : "aaaa"
3 valid words for "abslute" : "aaaa", "asas", "able"
2 valid words for "absoryz" : "aaaa", "asas"
4 valid words for "actresz" : "aaaa", "asas", "actt", "access"
There're no valid words for "gaswxyz" cause none of the words in the list contains letter 'g'.

 

Constraints:數組

  • 1 <= words.length <= 10^5
  • 4 <= words[i].length <= 50
  • 1 <= puzzles.length <= 10^4
  • puzzles[i].length == 7
  • words[i][j]puzzles[i][j] are English lowercase letters.
  • Each puzzles[i] doesn't contain repeated characters.

 外國友人仿照中國字謎設計了一個英文版猜字謎小遊戲,請你來猜猜看吧。微信

字謎的迷面 puzzle 按字符串形式給出,若是一個單詞 word 符合下面兩個條件,那麼它就能夠算做謎底:app

  • 單詞 word 中包含謎面 puzzle 的第一個字母。
  • 單詞 word 中的每個字母均可以在謎面 puzzle 中找到。
    例如,若是字謎的謎面是 "abcdefg",那麼能夠做爲謎底的單詞有 "faced", "cabbage", 和 "baggage";而 "beefed"(不含字母 "a")以及 "based"(其中的 "s" 沒有出如今謎面中)。

返回一個答案數組 answer,數組中的每一個元素 answer[i] 是在給出的單詞列表 words 中能夠做爲字謎迷面 puzzles[i] 所對應的謎底的單詞數目。spa

 

示例:設計

輸入:
words = ["aaaa","asas","able","ability","actt","actor","access"], 
puzzles = ["aboveyz","abrodyz","abslute","absoryz","actresz","gaswxyz"]
輸出:[1,1,3,2,4,0]
解釋:
1 個單詞能夠做爲 "aboveyz" 的謎底 : "aaaa" 
1 個單詞能夠做爲 "abrodyz" 的謎底 : "aaaa"
3 個單詞能夠做爲 "abslute" 的謎底 : "aaaa", "asas", "able"
2 個單詞能夠做爲 "absoryz" 的謎底 : "aaaa", "asas"
4 個單詞能夠做爲 "actresz" 的謎底 : "aaaa", "asas", "actt", "access"
沒有單詞能夠做爲 "gaswxyz" 的謎底,由於列表中的單詞都不含字母 'g'。

 

提示:code

  • 1 <= words.length <= 10^5
  • 4 <= words[i].length <= 50
  • 1 <= puzzles.length <= 10^4
  • puzzles[i].length == 7
  • words[i][j]puzzles[i][j] 都是小寫英文字母。
  • 每一個 puzzles[i] 所包含的字符都不重複。

Runtime: 656 ms
Memory Usage: 36.7 MB
 1 class Solution {  2     func findNumOfValidWords(_ words: [String], _ puzzles: [String]) -> [Int] {  3         var result:[Int] = [Int]()  4         var wordSets:[Int:Int] = [Int:Int]()  5         var puzzles = puzzles.map{Array($0).map{$0.ascii}}  6         var words = words.map{Array($0).map{$0.ascii - 97}}  7         // Encode word of 26 chars in 31 bit (signed Int)
 8         for i in 0..<words.count  9  { 10             var bits:Int = 0
11             for j in 0..<words[i].count 12  { 13                 bits |= 1 << words[i][j] 14  } 15             wordSets[bits,default:0] += 1
16  } 17 
18         for i in 0..<puzzles.count 19  { 20             var bits:Int = 0
21             var firstCharBitSet = 1 << (puzzles[i][0] - 97) 22             for j in 0..<puzzles[i].count 23  { 24                 bits |= 1 << (puzzles[i][j] - 97) 25  } 26             var count:Int = 0
27             var b:Int = bits 28             while(b > 0) 29  { 30                 if (b & firstCharBitSet) != 0 && wordSets[b] != nil 31  { 32                     count += wordSets[b]!
33  } 34                 b = --b & bits 35  } 36  result.append(count) 37  } 38         return result 39  } 40 } 41 
42 //Character擴展 
43 extension Character 44 { 45   //Character轉ASCII整數值(定義小寫爲整數值)
46    var ascii: Int { 47        get { 48            return Int(self.unicodeScalars.first?.value ?? 0) 49  } 50  } 51 } 52     
53 /*擴展Int類,實現自增++、自減--運算符*/
54 extension Int{ 55     //--前綴:先自減再執行表達示
56     static prefix func --(num:inout Int) -> Int { 57         //輸入輸出參數num
58         num -= 1
59         //返回減1後的數值
60         return num 61  } 62 }

1020ms

 1 class Solution {  2     func findNumOfValidWords(_ words: [String], _ puzzles: [String]) -> [Int] {  3         let table = Array("abcdefghijklmnopqrstuvwxyz")  4         var dic = [Character: Int](), i = 0
 5         for c in table {  6             dic[c] = i  7             i += 1
 8  }  9         var ans = [Int]() 10         var freq = [Int](repeating: 0, count: 1<<26) 11         for w in words { 12             let cw = Array(w) 13             var mask = 0
14             for c in cw { 15                 mask |= 1<<dic[c]!
16  } 17             freq[mask] += 1
18  } 19         for p in puzzles { 20             let cp = Array(p) 21             var mask = 0
22             for c in cp { 23                 mask |= 1<<dic[c]!
24  } 25 
26             let first = dic[cp.first!]!
27             var sub = mask 28             var total = 0
29             while true { 30                 if sub >> first & 1 != 0 { 31                     total += freq[sub] 32  } 33                 if sub == 0 { 34                     break
35  } 36                 sub = (sub-1)&mask 37  } 38  ans.append(total) 39  } 40         return ans 41  } 42 }

1908ms

 1 class Solution {  2     func findNumOfValidWords(_ words: [String], _ puzzles: [String]) -> [Int] {  3         let trie = Trie()  4         var result = [Int]()  5         
 6         for word in words {  7  trie.insert(String(Set(word).sorted()))  8  }  9         
10         for puzzle in puzzles { 11             let firstCharacter = puzzle[String.Index(encodedOffset: 0)] 12             let sortedPuzzle = String(puzzle.sorted()) 13             
14             result.append(trie.search(sortedPuzzle, firstCharacter, false)) 15  } 16         
17         return result 18  } 19 } 20 
21 class TrieNode { 22     var hash = [Character:TrieNode]() 23     var countOfWords = 0
24     
25     func search(_ word: String, _ firstChar: Character, _ firstSeen: Bool) -> Int { 26         var count = 0
27         
28         if firstSeen { 29             count += countOfWords 30  } 31         
32         for i in 0..<word.count { 33             let wordChar = word[String.Index(encodedOffset: i)] 34             
35             guard let childNode = hash[wordChar] else { continue } 36             
37             if wordChar == firstChar { 38                 count += childNode.search(word, firstChar, true) 39             } else { 40                 count += childNode.search(word, firstChar, firstSeen) 41  } 42             
43  } 44         
45         return count 46  } 47 } 48 
49 class Trie { 50     let root = TrieNode() 51     
52     init(_ words: [String] = []) { 53  words.forEach(insert) 54  } 55     
56     func search(_ word: String, _ firstChar: Character, _ firstSeen: Bool) -> Int { 57         return root.search(word, firstChar, firstSeen) 58  } 59     
60  func insert(_ word: String) { 61         var current = root 62         for character in word { 63             if let node = current.hash[character] { 64                 current = node 65             } else { 66                 current.hash[character] = TrieNode() 67                 current = current.hash[character]!
68  } 69  } 70         current.countOfWords += 1
71  } 72 }
相關文章
相關標籤/搜索