557 阅读2分钟

js构建最小堆

class MinHeap {

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

  // 获取父节点
  getParentIndex(index){
    return (index - 1) >> 1; // 获取商  
  }

  // 获取左子节点
  getLeftIndex(index){
    return index * 2 + 1;
  }

  // 获取右子节点
  getRightIndex(index){
    return index * 2 + 2;
  }
  
  // 交换值
  swap(index1, index2){
    const tmp = this.heap[index1];
    this.heap[index1] = this.heap[index2];
    this.heap[index2] = tmp;
  }

  // 上移方法
  shiftUp(index){
    if(index === 0) return; // 堆顶,无需上移
    // 拿到父亲节点
    const parentIndex = this.getParentIndex(index);
    // 根据条件交换
    if(this.heap[parentIndex] > this.heap[index]){
      this.swap(parentIndex, index);
      this.shiftUp(parentIndex); // 继续上移
    }
  }

  // 下移方法
  shiftDown(index){
    // 获取子节点
    const leftIndex = this.getLeftIndex(index);
    const rightIndex = this.getRightIndex(index);
    // 比较左侧
    if(this.heap[leftIndex] < this.heap[index]){
      this.swap(leftIndex, index);
      this.shiftDown(leftIndex);
    }
    // 比较右侧
    if(this.heap[rightIndex] < this.heap[index]){
      this.swap(rightIndex, index);
      this.shiftDown(rightIndex);
    }
  }

  // 插入方法
  insert(value) {
    this.heap.push(value); // 先放到最后一位
    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;
  }
}

LeetCode 215 数组中第k大元素

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number}
 */


class MinHeap {

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

  // 获取父节点
  getParentIndex(index){
    return (index - 1) >> 1; // 获取商  
  }

  // 获取左子节点
  getLeftIndex(index){
    return index * 2 + 1;
  }

  // 获取右子节点
  getRightIndex(index){
    return index * 2 + 2;
  }
  
  // 交换值
  swap(index1, index2){
    const tmp = this.heap[index1];
    this.heap[index1] = this.heap[index2];
    this.heap[index2] = tmp;
  }

  // 上移方法
  shiftUp(index){
    if(index === 0) return; // 堆顶,无需上移
    // 拿到父亲节点
    const parentIndex = this.getParentIndex(index);
    // 根据条件交换
    if(this.heap[parentIndex] > this.heap[index]){
      this.swap(parentIndex, index);
      this.shiftUp(parentIndex); // 继续上移
    }
  }

  // 下移方法
  shiftDown(index){
    // 获取子节点
    const leftIndex = this.getLeftIndex(index);
    const rightIndex = this.getRightIndex(index);
    // 比较左侧
    if(this.heap[leftIndex] < this.heap[index]){
      this.swap(leftIndex, index);
      this.shiftDown(leftIndex);
    }
    // 比较右侧
    if(this.heap[rightIndex] < this.heap[index]){
      this.swap(rightIndex, index);
      this.shiftDown(rightIndex);
    }
  }

  // 插入方法
  insert(value) {
    this.heap.push(value); // 先放到最后一位
    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;
  }
}

var findKthLargest = function(nums, k) {
    const h = new MinHeap();
    nums.forEach(n => {
        h.insert(n);
        if(h.size() > k){
            h.pop();
        }
    });
    return h.peek();
};

LeetCode 347 前 K 个高频元素

/**
 * @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);
    });
    // console.log(map);
    const list = Array.from(map).sort((a, b) => b[1] - a[1]);
    // console.log(list);
    return list.slice(0, k).map(n => n[0]);
};

用堆来做:

/**
 * @param {number[]} nums
 * @param {number} k
 * @return {number[]}
 */

class MinHeap {

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

  // 获取父节点
  getParentIndex(index){
    return (index - 1) >> 1; // 获取商  
  }

  // 获取左子节点
  getLeftIndex(index){
    return index * 2 + 1;
  }

  // 获取右子节点
  getRightIndex(index){
    return index * 2 + 2;
  }
  
  // 交换值
  swap(index1, index2){
    const tmp = this.heap[index1];
    this.heap[index1] = this.heap[index2];
    this.heap[index2] = tmp;
  }

  // 上移方法
  shiftUp(index){
    if(index === 0) return; // 堆顶,无需上移
    // 拿到父亲节点
    const parentIndex = this.getParentIndex(index);
    // 根据条件交换
    if(this.heap[parentIndex] && this.heap[parentIndex].value > this.heap[index].value){
      this.swap(parentIndex, index);
      this.shiftUp(parentIndex); // 继续上移
    }
  }

  // 下移方法
  shiftDown(index){
    // 获取子节点
    const leftIndex = this.getLeftIndex(index);
    const rightIndex = this.getRightIndex(index);
    // 比较左侧
    if(this.heap[leftIndex] && this.heap[leftIndex].value < this.heap[index].value){
      this.swap(leftIndex, index);
      this.shiftDown(leftIndex);
    }
    // 比较右侧
    if(this.heap[rightIndex] && this.heap[rightIndex].value < this.heap[index].value){
      this.swap(rightIndex, index);
      this.shiftDown(rightIndex);
    }
  }

  // 插入方法
  insert(value) {
    this.heap.push(value); // 先放到最后一位
    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;
  }
}

var topKFrequent = function(nums, k) {
    const map = new Map();
    nums.forEach(n => {
        map.set(n, map.has(n) ? map.get(n) + 1 : 1);
    });
    const h = new MinHeap();
    map.forEach((value, key) => {
        h.insert({value, key});
        if(h.size() > k){
            h.pop();
        }
    });
    return h.heap.map(a => a.key);
};

LeetCode 23 合并k个排序链表

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode[]} lists
 * @return {ListNode}
 */

class MinHeap {

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

  // 获取父节点
  getParentIndex(index){
    return (index - 1) >> 1; // 获取商  
  }

  // 获取左子节点
  getLeftIndex(index){
    return index * 2 + 1;
  }

  // 获取右子节点
  getRightIndex(index){
    return index * 2 + 2;
  }
  
  // 交换值
  swap(index1, index2){
    const tmp = this.heap[index1];
    this.heap[index1] = this.heap[index2];
    this.heap[index2] = tmp;
  }

  // 上移方法
  shiftUp(index){
    if(index === 0) return; // 堆顶,无需上移
    // 拿到父亲节点
    const parentIndex = this.getParentIndex(index);
    // 根据条件交换
    if(this.heap[parentIndex] && this.heap[parentIndex].val > this.heap[index].val){
      this.swap(parentIndex, index);
      this.shiftUp(parentIndex); // 继续上移
    }
  }

  // 下移方法
  shiftDown(index){
    // 获取子节点
    const leftIndex = this.getLeftIndex(index);
    const rightIndex = this.getRightIndex(index);
    // 比较左侧
    if(this.heap[leftIndex] && this.heap[leftIndex].val < this.heap[index].val){
      this.swap(leftIndex, index);
      this.shiftDown(leftIndex);
    }
    // 比较右侧
    if(this.heap[rightIndex] && this.heap[rightIndex].val < this.heap[index].val){
      this.swap(rightIndex, index);
      this.shiftDown(rightIndex);
    }
  }

  // 插入方法
  insert(value) {
    this.heap.push(value); // 先放到最后一位
    this.shiftUp(this.heap.length - 1); // 上移操作
  }

  // 删除堆顶
  pop(){
    if(this.size() === 1) return this.heap.shift();
    const top = this.heap[0];
    this.heap[0] = this.heap.pop();
    this.shiftDown(0);
    return top;
  }

  // 获取堆顶
  peek(){
    return this.heap[0];
  }

  // 获取堆的大小
  size(){
    return this.heap.length;
  }
}


var mergeKLists = function(lists) {
    const res = new ListNode(0);
    const h = new MinHeap(); //
    let p = res;
    lists.forEach(l => {
        if(l) h.insert(l);
    });
    while(h.size()){
        const n = h.pop(); // 弹出最小值
        p.next = n;
        p = p.next;
        if(n.next) h.insert(n.next); // 插入
    }
    return res.next;
};