Skip to content

Commit 7697690

Browse files
authored
Update 642-design-search-autocomplete-system.js
1 parent 61b3b3a commit 7697690

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed

642-design-search-autocomplete-system.js

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,154 @@ Trie.prototype.stringsStartingWith = function (prefix) {
105105
traverse(curr, prefix)
106106
return results
107107
}
108+
109+
// another
110+
111+
class TrieNode {
112+
constructor() {
113+
this.children = new Map()
114+
this.counts = new Map()
115+
this.isWord = false
116+
}
117+
}
118+
119+
class Pair {
120+
constructor(s, c) {
121+
this.str = s
122+
this.cnt = c
123+
}
124+
}
125+
126+
/**
127+
* @param {string[]} sentences
128+
* @param {number[]} times
129+
*/
130+
const AutocompleteSystem = function (sentences, times) {
131+
this.root = new TrieNode()
132+
this.prefix = ''
133+
for (let i = 0, n = sentences.length; i < n; i++) {
134+
this.add(sentences[i], times[i])
135+
}
136+
}
137+
138+
AutocompleteSystem.prototype.add = function (str, cnt) {
139+
let cur = this.root
140+
for (const ch of str) {
141+
let next = cur.children.get(ch)
142+
if (next == null) {
143+
next = new TrieNode()
144+
cur.children.set(ch, next)
145+
}
146+
cur = next
147+
cur.counts.set(str, (cur.counts.get(str) || 0) + cnt)
148+
}
149+
cur.isWord = true
150+
}
151+
152+
/**
153+
* @param {character} c
154+
* @return {string[]}
155+
*/
156+
AutocompleteSystem.prototype.input = function (c) {
157+
if (c === '#') {
158+
this.add(this.prefix, 1)
159+
this.prefix = ''
160+
return []
161+
}
162+
this.prefix += c
163+
let cur = this.root
164+
for (const ch of this.prefix) {
165+
const next = cur.children.get(ch)
166+
if (next == null) {
167+
return []
168+
}
169+
cur = next
170+
}
171+
const pq = new PriorityQueue((a, b) =>
172+
a.cnt === b.cnt ? a.str.localeCompare(b.str) < 0 : a.cnt > b.cnt
173+
)
174+
175+
for(const s of cur.counts.keys()) {
176+
pq.push(new Pair(s, cur.counts.get(s)))
177+
}
178+
const res = []
179+
for(let i = 0; i < 3 && pq.size(); i++) {
180+
res.push(pq.pop().str)
181+
}
182+
183+
return res
184+
}
185+
186+
/**
187+
* Your AutocompleteSystem object will be instantiated and called as such:
188+
* var obj = new AutocompleteSystem(sentences, times)
189+
* var param_1 = obj.input(c)
190+
*/
191+
192+
class PriorityQueue {
193+
constructor(comparator = (a, b) => a > b) {
194+
this.heap = []
195+
this.top = 0
196+
this.comparator = comparator
197+
}
198+
size() {
199+
return this.heap.length
200+
}
201+
isEmpty() {
202+
return this.size() === 0
203+
}
204+
peek() {
205+
return this.heap[this.top]
206+
}
207+
push(...values) {
208+
values.forEach((value) => {
209+
this.heap.push(value)
210+
this.siftUp()
211+
})
212+
return this.size()
213+
}
214+
pop() {
215+
const poppedValue = this.peek()
216+
const bottom = this.size() - 1
217+
if (bottom > this.top) {
218+
this.swap(this.top, bottom)
219+
}
220+
this.heap.pop()
221+
this.siftDown()
222+
return poppedValue
223+
}
224+
replace(value) {
225+
const replacedValue = this.peek()
226+
this.heap[this.top] = value
227+
this.siftDown()
228+
return replacedValue
229+
}
230+
231+
parent = (i) => ((i + 1) >>> 1) - 1
232+
left = (i) => (i << 1) + 1
233+
right = (i) => (i + 1) << 1
234+
greater = (i, j) => this.comparator(this.heap[i], this.heap[j])
235+
swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]])
236+
siftUp = () => {
237+
let node = this.size() - 1
238+
while (node > this.top && this.greater(node, this.parent(node))) {
239+
this.swap(node, this.parent(node))
240+
node = this.parent(node)
241+
}
242+
}
243+
siftDown = () => {
244+
let node = this.top
245+
while (
246+
(this.left(node) < this.size() && this.greater(this.left(node), node)) ||
247+
(this.right(node) < this.size() && this.greater(this.right(node), node))
248+
) {
249+
let maxChild =
250+
this.right(node) < this.size() &&
251+
this.greater(this.right(node), this.left(node))
252+
? this.right(node)
253+
: this.left(node)
254+
this.swap(node, maxChild)
255+
node = maxChild
256+
}
257+
}
258+
}

0 commit comments

Comments
 (0)