[路飞]_LeetCode_23. 合并K个升序链表-多路归并

506 阅读1分钟

「这是我参与2022首次更文挑战的第30天,活动详情查看:2022首次更文挑战

题目

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

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

示例 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 == lists.length
0 <= k <= 10^4
0 <= lists[i].length <= 500
-10^4 <= lists[i][j] <= 10^4
lists[i] 按 升序 排列
lists[i].length 的总和不超过 10^4

来源:力扣(LeetCode)leetcode-cn.com/problems/me…

解题思路

题目中给出的链表是升序链表,对有序的链表进行排序可以使用归并排序,这道题是对多个链表进行排序,所以是多路归并排序。

具体过程:

  1. 用一个小顶堆存放链表的引用地址;
  2. 依次取堆顶元素拼接在新链表后面;
  3. 弹出堆顶元素;
  4. 如果堆顶元素的下个节点不为空,则将该节点入队列;

代码实现

var mergeKLists = function (lists) {
    //创建小顶堆
    const q = new MinPriorityQueue()

    //将所有不为空的链表入小顶堆
    lists.forEach(list => {
        if (list) q.enqueue(list, list.val)
    })

    //创建新链表的虚拟头节点
    const res = new ListNode(null)
    let cur = res
    while (!q.isEmpty()) {
        //取小顶堆的堆顶元素
        const node = q.front()['element']
        
        //当前节点的下个节点指向堆顶元素
        cur.next = node
        //当前节点后移
        cur = cur.next
        //堆顶元素弹出
        q.dequeue()
        
        //如果取出的堆顶元素下个节点不为空,则将下个节点入队列
        if (node.next) q.enqueue(node.next, node.next.val)
    }

    //返回虚拟节点的下个节点
    return res.next
};

如有错误欢迎指出,欢迎一起讨论!