合并k个已排序的链表

合并 k 个升序的链表并将结果作为一个升序的链表返回其头节点。

 public ListNode mergeKLists(ListNode[] lists) {  
        // 创建一个优先队列,根据节点的值进行排序  
        PriorityQueue<ListNode> pq = new PriorityQueue<>((a, b) -> a.val - b.val);  
  
        // 将所有链表的头节点加入优先队列  
        for (ListNode list : lists) {  
            if (list != null) {  
                pq.offer(list);  
            }  
        }  
  
        // 创建一个哨兵节点和当前节点指针  
        ListNode dummy = new ListNode(0);  
        ListNode current = dummy;  
  
        // 当优先队列不为空时,不断取出最小值并接入到新链表中  
        while (!pq.isEmpty()) {  
            ListNode minNode = pq.poll(); // 取出当前最小的节点  
            current.next = minNode; // 接入到新链表中  
            current = current.next; // 移动当前节点指针  
  
            // 如果取出的节点有后继节点,则将后继节点加入优先队列  
            if (minNode.next != null) {  
                pq.offer(minNode.next);  
            }  
        }  
  
        // 返回合并后链表的头节点(跳过哨兵节点)  
        return dummy.next;  
    }  

        这段代码实现了合并 k 个有序链表的功能,并返回合并后的有序链表。下面是对该代码的详细讲解:

函数签名

public ListNode mergeKLists(ArrayList<ListNode> lists)

        这个函数接收一个 ArrayList<ListNode> 类型的参数 lists,其中 lists 是一个包含多个链表头节点的列表(即数组)。每个链表都是有序的,且链表的节点定义为 ListNode 类型。函数返回一个合并后的有序链表的头节点。

优先队列(PriorityQueue)

        为了有效地合并这些链表,代码使用了一个最小堆(优先队列)来存储所有链表的当前最小节点。优先队列的比较器是根据节点的 val 值来定义的,确保每次从队列中取出的都是当前所有链表节点中的最小值。

PriorityQueue<ListNode> pq = new PriorityQueue<>((a, b) -> a.val - b.val);

        这行代码创建了一个最小堆,其中 a.val - b.val 用于定义节点之间的比较逻辑,即根据节点的 val 值进行升序排序。

初始化优先队列

        接下来,代码遍历 lists 数组,将每个链表的头节点(如果非空)添加到优先队列中。

for (ListNode list : lists) {
if (list != null) {
pq.offer(list);
}
}

合并链表

        为了合并这些链表,代码使用了一个哑节点(dummy node)和一个当前节点(current node)来构建合并后的链表。哑节点是一个不存储实际数据的节点,它的 next 指针将指向合并后的链表的第一个真实节点。当前节点则用于遍历和构建合并后的链表。

 
ListNode dummy = new ListNode(0);
ListNode current = dummy;

然后,代码进入一个循环,直到优先队列为空。在每次循环中,它执行以下操作:

  1. 从优先队列中取出当前所有链表节点中的最小值(即队列的头部节点),并将其连接到当前节点的 next 指针上。
ListNode minNode = pq.poll();
current.next = minNode;
current = current.next;
  1. 如果取出的节点(minNode)还有下一个节点(即 minNode.next 不为空),则将这个下一个节点添加到优先队列中,以便在后续迭代中考虑。
if (minNode.next != null) {
pq.offer(minNode.next);
}

返回结果

        最后,函数返回哑节点的下一个节点,即合并后的链表的头节点。由于哑节点不存储实际数据,它的 next 指针将指向合并后的链表的第一个真实节点。

return dummy.next;

总结

        这段代码通过优先队列高效地合并了 k 个有序链表。它首先将所有链表的头节点添加到优先队列中,然后逐个取出队列中的最小节点,并将其连接到合并后的链表中。通过这种方式,它能够保持合并后的链表也是有序的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值