图解Leecode第23题-合并K个升序链表(附Java实现代码)

250 阅读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

这里使用到一个库函数优先级队列--PriorityQueue 首先附上完整实现代码:

import java.util.PriorityQueue;
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length==0) return null;

        //虚拟头结点
        ListNode HGuard=new ListNode(-1);
        ListNode p=HGuard;

        //优先级队列,最小堆
        PriorityQueue<ListNode> pq=new PriorityQueue<>(lists.length,(a,b)->(a.val-b.val));

        for(ListNode head:lists){
            if(head!=null){
                pq.add(head);
            }
        }

        while(!pq.isEmpty()){
            ListNode node=pq.poll();
            p.next=node;
            if(node.next != null){
                pq.add(node.next);
            }
            p=p.next;
        }

        return HGuard.next;

    }
}

代码解读: PriorityQueue<ListNode> pq=new PriorityQueue<>(lists.length,(a,b)->(a.val-b.val));这段代码构造一个优先队列,(a,b)->(a.val-b.val)表示最小值优先(相当于Comparable接口)。

然后通过循环

for(ListNode head:lists){
            if(head!=null){
                pq.add(head);
            }
        }

将每一个链表的头结点放进去,如图所示:

111.png

接下来每一次循环弹出队列元素中的最小值。并且,每一次弹出之后,将该结点的下一个结点再次加入到优先级队列中,直到读出所有结点为止。

(下面的图片展示每一步代码执行后的结果)

前两次分别弹出两个1: 111_20220617213238.png

222_20220617213506.png

每次弹出之后,剩下的链表结点在里面根据最小优先再次排序,以此类推: 333.png

444.png

555.png

666.png

777.png

最后得出结果1 -> 1 -> 2 -> 3 -> 4 -> 4 -> 5 -> 6

最后提交到leecode上面执行通过:

felix.png