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

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:爲敢(WeiGanTechnologies)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/
➤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 }
相關文章
相關標籤/搜索