Top K Frequent Elements
Given an integer array nums and an integer k, return the top k frequent elements in the array.
Constraints:
- 1 <= nums.length <= 10^5
 - 1 <= k <= 10^5
 - It is guaranteed that the answer is unique.
 
Examples:
Input: [1,1,1,2,2,3] and k = 2
Output: [1,2]
Explanation: The elements 1 and 2 are the top 2 frequent elements in the array.
Solutions
Hash Table and Heap
We use a hash table to count the frequency of each element in the array. Then we use a max heap to find the top k frequent elements.
function topKFrequent(nums, k) {
  const count = {};
  for (let num of nums) {
    count[num] = (count[num] || 0) + 1;
  }
  const maxHeap = new MaxHeap(
    Object.keys(count),
    (a, b) => count[b] - count[a]
  );
  const result = [];
  for (let i = 0; i < k; i++) {
    result.push(maxHeap.extractMax());
  }
  return result;
}
class MaxHeap {
  constructor(data, comparator) {
    this.data = data;
    this.comparator = comparator;
    this.heapify();
  }
  heapify() {
    for (let i = Math.floor(this.data.length / 2) - 1; i >= 0; i--) {
      this.siftDown(i);
    }
  }
  siftDown(index) {
    let smallest = index;
    let left = 2 * index + 1;
    let right = 2 * index + 2;
    if (
      left < this.data.length &&
      this.comparator(this.data[smallest], this.data[left]) > 0
    ) {
      smallest = left;
    }
    if (
      right < this.data.length &&
      this.comparator(this.data[smallest], this.data[right]) > 0
    ) {
      smallest = right;
    }
    if (smallest !== index) {
      [this.data[index], this.data[smallest]] = [
        this.data[smallest],
        this.data[index],
      ];
      this.siftDown(smallest);
    }
  }
  extractMax() {
    if (this.data.length === 0) return null;
    if (this.data.length === 1) return this.data.pop();
    const max = this.data[0];
    this.data[0] = this.data.pop();
    this.siftDown(0);
    return max;
  }
}
Follow-up:
What if the input array is very large and does not fit into memory?

