[路飞]_leetcode_23.合并K个升序链表

155 阅读1分钟

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例 1:

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
  1->4->5,
  1->3->4,
  2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6

示例 2:

输入:lists = []
输出:[]

示例 3:

输入:lists = [[]]
输出:[]

解题思路

这一题是多个链表合并,每个链表的值都已经按升序排序好了,所以我们可以将链表看成是一个值,然后在k个元素中找最小值,那么我们可以知道找最小值需要通过小顶堆来实现。

  1. 首先先把k个链表的头节点放到小顶堆中
  2. 设置一个虚拟头节点来维护最后合并链表的头节点
  3. 当小顶堆不为空时,每次从堆中取一个链表,将这个链表的头节点放到虚拟头节点链表的尾部
  4. 如果这个链表还有下一个节点,则将这个链表头节点的下一个节点放到堆中,否则不需要
  5. 重复上述2-4过程直到堆为空,返回虚拟头节点后的链表

代码

class Heap {
    constructor() {
        this.data = [];
    }

    swap(i, j) {
        [this.data[i], this.data[j]] = [this.data[j], this.data[i]]
    }

    compartor(i, j) {
        return this.data[i].val - this.data[j].val;
    }

    size() {
        return this.data.length;
    }

    peek() {
        if (!this.size()) return null;
        return this.data[0]
    }

    offer(val) {
        this.data.push(val);
        this.bubbleUp(this.data.length-1);
    }

    pop() {
        if (!this.size()) return null;
        let res = this.data[0];
        if (this.size() > 1) {
            this.data[0] = this.data.pop();
            this.bubbleDown(0);
        } else {
            this.data.pop();
        }
        return res;
    }

    bubbleUp(index) {
        while(index) {
            let parent = (index - 1) >> 1;
            if (this.compartor(index, parent) < 0) {
                this.swap(index, parent);
                index = parent;
            } else {
                break;
            }
        }
    }

    bubbleDown(index) {
        let last = this.data.length - 1;
        while(index < last) {
            let temp = index, left = index * 2 + 1, right = index * 2 + 2;
            if (left <= last && this.compartor(left, temp) < 0) {
                temp = left;
            }
            if (right <= last && this.compartor(right, temp) < 0) {
                temp = right;
            }
            if (temp == index) break;
            this.swap(temp, index);
            index = temp;
        }
    }
}
var mergeKLists = function(lists) {
    let h = new Heap()
    for (const head of lists) {
        if (head == null) continue
        h.offer(head)
    }

    let ret = new ListNode(-1), p = ret
    while(h.size() > 0) {
        let cur = h.pop()
        p.next = cur
        p = cur
        if (cur.next) h.offer(cur.next)
    }
    return ret.next
};