★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(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
.word
, that letter is in 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.puzzles[i]
doesn't contain repeated characters.外國友人仿照中國字謎設計了一個英文版猜字謎小遊戲,請你來猜猜看吧。微信
字謎的迷面 puzzle
按字符串形式給出,若是一個單詞 word
符合下面兩個條件,那麼它就能夠算做謎底:app
word
中包含謎面 puzzle
的第一個字母。word
中的每個字母均可以在謎面 puzzle
中找到。返回一個答案數組 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]
所包含的字符都不重複。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 }