Skip to content

LeetCode:23. 合并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].val < this.heap[parentIndex].val
    ) {
      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].val > this.heap[leftIndex].val
    ) {
      this.swap(index, leftIndex);
      this.shiftDown(leftIndex);
    }

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

  insert(val) {
    // 插入新值
    this.heap.push(val);
    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;
  }
}

/**
 * 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}
 */
var mergeKLists = function (lists) {
  const res = new ListNode(0);
  const h = new MinHeap();
  let p = res;

  // 推到堆中得到 MinHeap { heap: [ [1,4,5], [1,3,4], [2,6] ] }
  lists.forEach((l) => {
    if (l) h.insert(l);
  });

  while (h.size()) {
    // 分别弹出 [1,4,5], [1,3,4], [2,6] 链表
    const n = h.pop();
    p.next = n; // {val:1} 这种结构
    p = p.next;
    if (n.next) h.insert(n.next);
  }

  return res.next;
};

发现使用数组排序也挺好的

js
/**
 * 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}
 */
var mergeKLists = function (lists) {
  // 发现用数组排序也行
  let list = [];
  for (let i = 0; i < lists.length; i++) {
    let node = lists[i];
    while (node) {
      list.push(node.val);
      node = node.next;
    }
  }

  list = list.sort((a, b) => a - b);

  let res = new ListNode(0);
  let p = res;
  list.forEach((n) => {
    p.next = new ListNode(n);
    p = p.next;
  });

  return res.next;
};

基于 MIT 许可发布