LeetCode Solutions
642. Design Search Autocomplete System
Time: Constructor: $O(\Sigma |\texttt{sentences[i]}|)$, input(c: chr): $O(1)$ Space: $O(\Sigma |\texttt{sentences[i]}|)$
class TrieNode implements Comparable<TrieNode> {
public TrieNode[] children = new TrieNode[128];
public String s = null;
public int time = 0;
public List<TrieNode> top3 = new ArrayList<>();
public int compareTo(TrieNode o) {
if (this.time == o.time)
return this.s.compareTo(o.s);
return o.time - this.time;
}
public void update(TrieNode node) {
if (!this.top3.contains(node))
this.top3.add(node);
Collections.sort(top3);
if (top3.size() > 3)
top3.remove(top3.size() - 1);
}
}
class AutocompleteSystem {
public AutocompleteSystem(String[] sentences, int[] times) {
for (int i = 0; i < sentences.length; ++i)
insert(sentences[i], times[i]);
}
public List<String> input(char c) {
if (c == '#') {
insert(sb.toString(), 1);
curr = root;
sb = new StringBuilder();
return new ArrayList<>();
}
sb.append(c);
if (curr != null)
curr = curr.children[c];
if (curr == null)
return new ArrayList<>();
List<String> ans = new ArrayList<>();
for (TrieNode node : curr.top3)
ans.add(node.s);
return ans;
}
private TrieNode root = new TrieNode();
private TrieNode curr = root;
private StringBuilder sb = new StringBuilder();
private void insert(final String s, int time) {
TrieNode node = root;
for (final char c : s.toCharArray()) {
if (node.children[c] == null)
node.children[c] = new TrieNode();
node = node.children[c];
}
node.s = s;
node.time += time;
// Walk the path again and update the node with leaf node
TrieNode leaf = node;
node = root;
for (final char c : s.toCharArray()) {
node = node.children[c];
node.update(leaf);
}
}
}
class TrieNode:
def __init__(self):
self.children: Dict[chr, TrieNode] = {}
self.s: Optional[str] = None
self.time = 0
self.top3: List[TrieNode] = []
def __lt__(self, other):
if self.time == other.time:
return self.s < other.s
return self.time > other.time
def update(self, node) -> None:
if node not in self.top3:
self.top3.append(node)
self.top3.sort()
if len(self.top3) > 3:
self.top3.pop()
class AutocompleteSystem:
def __init__(self, sentences: List[str], times: List[int]):
self.root = TrieNode()
self.curr = self.root
self.s: List[chr] = []
for sentence, time in zip(sentences, times):
self._insert(sentence, time)
def input(self, c: str) -> List[str]:
if c == '#':
self._insert(''.join(self.s), 1)
self.curr = self.root
self.s = []
return []
self.s.append(c)
if self.curr:
self.curr = self.curr.children.get(c, None)
if not self.curr:
return []
return [node.s for node in self.curr.top3]
def _insert(self, sentence: str, time: int) -> None:
node = self.root
for c in sentence:
if c not in node.children:
node.children[c] = TrieNode()
node = node.children[c]
node.s = sentence
node.time += time
leaf = node
node: TrieNode = self.root
for c in sentence:
node = node.children[c]
node.update(leaf)