通过堆的方式实现

  • 时间复杂度:O (n * log k)
  • 空间复杂度:O (n)

    1. function topKFrequent(nums, k) {
    2. const map = new Map();
    3. nums.forEach((n) => {
    4. map.set(n, map.has(n) ? map.get(n) + 1 : 1);
    5. });
    6. const h = new MinHeap();
    7. map.forEach((value, key) => {
    8. h.insert({ value, key });
    9. if (h.size() > k) {
    10. h.pop();
    11. }
    12. });
    13. return h.heap.map((x) => x.key);
    14. }

代码中有两个 forEach 循环,他们的时间复杂度分别是 O (n),而我们知道堆的 insertpop 的时间复杂度分别是 O (log k ) ,所以该函数的时间复杂度为 O (n * log k) k 代表数组中不相同元素的个数。空间复杂度是 O (n),因为主要看 map 中存放不同元素的个数,最坏情况是 nums 数组的长度。

改造了一下堆构造函数

  1. class MinHeap {
  2. constructor() {
  3. this.heap = [];
  4. }
  5. top() {
  6. return this.heap[0];
  7. }
  8. size() {
  9. return this.heap.length;
  10. }
  11. getChildLeftIndex(i) {
  12. return i * 2 + 1;
  13. }
  14. getChildRightIndex(i) {
  15. return i * 2 + 2;
  16. }
  17. getParentIndex(i) {
  18. return (i - 1) >> 1;
  19. }
  20. swap(index1, index2) {
  21. const temp = this.heap[index1];
  22. this.heap[index1] = this.heap[index2];
  23. this.heap[index2] = temp;
  24. }
  25. shiftUp(index) {
  26. if (index === 0) return;
  27. const parentIndex = this.getParentIndex(index);
  28. if (this.heap[parentIndex] && this.heap[parentIndex].value > this.heap[index].value) {
  29. this.swap(parentIndex, index);
  30. this.shiftUp(parentIndex);
  31. }
  32. }
  33. shiftDown(index) {
  34. const leftChildIndex = this.getChildLeftIndex(index);
  35. const rightChildIndex = this.getChildRightIndex(index);
  36. if (this.heap[leftChildIndex] && this.heap[leftChildIndex].value < this.heap[index].value) {
  37. this.swap(leftChildIndex, index);
  38. this.shiftDown(leftChildIndex);
  39. }
  40. if (this.heap[rightChildIndex] && this.heap[rightChildIndex].value < this.heap[index].value) {
  41. this.swap(rightChildIndex, index);
  42. this.shiftDown(rightChildIndex);
  43. }
  44. }
  45. insert(value) {
  46. this.heap.push(value);
  47. this.shiftUp(this.heap.length - 1);
  48. }
  49. pop() {
  50. this.heap[0] = this.heap.pop();
  51. this.shiftDown(0);
  52. }
  53. }