forked from soapyigu/LeetCode-Swift
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SearchSuggestionsSystem.swift
72 lines (55 loc) · 1.92 KB
/
SearchSuggestionsSystem.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/**
* Question Link: https://leetcode.com/problems/search-suggestions-system/
* Primary idea: Use trie to add and search prefix (DFS).
*
* Time Complexity: O(n), Space Complexity: O(n)
*
*/
class SearchSuggestionsSystem {
func suggestedProducts(_ products: [String], _ searchWord: String) -> [[String]] {
let trie = Trie()
var res = [[String]]()
products.forEach { trie.insert($0) }
return (1...searchWord.count).map { trie.searchWords(for: String(searchWord.prefix($0))) }
}
private class Trie {
let root = TrieNode()
func insert(_ word: String) {
var node = root
for char in word {
if node.charNodeMap[char] == nil {
node.charNodeMap[char] = TrieNode()
}
node = node.charNodeMap[char]!
}
node.isWord = true
}
func searchWords(for term: String) -> [String] {
var res = [String](), node = root
for char in term {
guard let next = node.charNodeMap[char] else {
return res
}
node = next
}
dfs(&res, term, node)
return Array(res.sorted().prefix(3))
}
private func dfs(_ res: inout [String], _ path: String, _ node: TrieNode) {
if node.isWord {
res.append(path)
}
for (char, next) in node.charNodeMap {
dfs(&res, path + String(char), next)
}
}
}
private class TrieNode {
var isWord: Bool
var charNodeMap: [Character: TrieNode]
init() {
isWord = false
charNodeMap = [Character: TrieNode]()
}
}
}