Skip to content

LeetCode:347. 前 K 个高频元素

使用最小堆方法

js
/**
 * JavaScript 实现:最小堆类
 * 插入
 * 删除
 * 返回堆头
 * 返回堆长
 */

class MinHeap {
  constructor() {
    this.heap = [];
  }

  swap(i1, i2) {
    // 交换两个值
    const temp = this.heap[i1];
    this.heap[i1] = this.heap[i2];
    this.heap[i2] = temp;
  }

  getParentIndex(i) {
    // 获取父元素的索引值 (index-1)/2
    // 类似 Math.floor((index-1/2))
    return (i - 1) >> 1;
  }

  getLeftIndex(i) {
    // 获取左元素的索引值 i*2+1
    // 类似 Math.floor((index-1/2))
    return i * 2 + 1;
  }

  getRightIndex(i) {
    // 获取右元素的索引值 i*2+2
    // 类似 Math.floor((index-1/2))
    return i * 2 + 2;
  }

  shiftUp(index) {
    if (index === 0) return;

    const parentIndex = this.getParentIndex(index);

    // 较小的值 上移
    if (
      this.heap[parentIndex] &&
      this.heap[index].value < this.heap[parentIndex].value
    ) {
      this.swap(index, parentIndex);
      this.shiftUp(parentIndex);
    }
  }

  shiftDown(index) {
    const leftIndex = this.getLeftIndex(index);
    const rightIndex = this.getRightIndex(index);

    // 较大的值 下移
    if (
      this.heap[leftIndex] &&
      this.heap[index].value > this.heap[leftIndex].value
    ) {
      this.swap(index, leftIndex);
      this.shiftDown(leftIndex);
    }

    // 较大的值 下移
    if (
      this.heap[rightIndex] &&
      this.heap[index].value > this.heap[rightIndex].value
    ) {
      this.swap(index, rightIndex);
      this.shiftDown(rightIndex);
    }
  }

  insert(val) {
    // 插入新值
    this.heap.push(val);
    this.shiftUp(this.heap.length - 1);
  }
  pop() {
    // 删除值,用堆尾替换堆顶
    this.heap[0] = this.heap.pop();

    // 然后把较大值下移
    this.shiftDown(0);
  }
  peek() {
    // 返回堆顶
    return this.heap[0];
  }

  size() {
    // 返回堆容量
    return this.heap.length;
  }
}

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var topKFrequent = function (nums, k) {
  const map = new Map();
  const h = new MinHeap();

  // 计算每个元素的个数
  nums.forEach((n) => {
    map.set(n, map.has(n) ? map.get(n) + 1 : 1);
  });

  // 根据 value 比较得个数最多的元素
  map.forEach((value, key) => {
    h.insert({ value, key });
    if (h.size() > k) {
      h.pop();
    }
  });

  // 输出元素
  return h.heap.map((n) => n.key);
};

拍脑袋直接输出

js
/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */
var topKFrequent = function (nums, k) {
  const map = new Map();

  nums.forEach((n) => {
    map.set(n, map.has(n) ? map.get(n) + 1 : 1);
  });

  const arr = Array.from(map).sort((a, b) => b[1] - a[1]);

  return arr.slice(0, k).map((n) => n[0]);
};

基于 MIT 许可发布