Count, then heap
javascript
class PriorityQueue {
items = []
constructor(compare = (a, b) => a - b) { this.compare = compare }
get size() { return this.items.length }
push(v) {
this.items.push(v)
let i = this.items.length - 1
while (i > 0) {
const p = (i - 1) >> 1
if (this.compare(this.items[p], this.items[i]) <= 0) break
;[this.items[p], this.items[i]] = [this.items[i], this.items[p]]
i = p
}
}
pop() {
if (!this.items.length) return undefined
const top = this.items[0]
const last = this.items.pop()
if (this.items.length) {
this.items[0] = last
let i = 0
while (true) {
const l = 2 * i + 1, r = 2 * i + 2
let s = i
if (l < this.items.length && this.compare(this.items[l], this.items[s]) < 0) s = l
if (r < this.items.length && this.compare(this.items[r], this.items[s]) < 0) s = r
if (s === i) break
;[this.items[i], this.items[s]] = [this.items[s], this.items[i]]
i = s
}
}
return top
}
}
function topKFrequent(items, k) {
const counts = new Map()
for (const item of items) counts.set(item, (counts.get(item) || 0) + 1)
const heap = new PriorityQueue((a, b) => a.count - b.count)
for (const [value, count] of counts) {
heap.push({ value, count })
if (heap.size > k) heap.pop()
}
const out = []
while (heap.size) out.push(heap.pop().value)
return out.reverse()
}
console.log(topKFrequent(["a", "b", "a", "c", "a", "b"], 2))