力扣23. 合并 K 个升序链表(java,最小堆解法)

Problem: 23. 合并 K 个升序链表

文章目录

题目描述

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

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

思路

1.对于合并k个有序链表,我们较为容易想到的是用k个指针指向k个链表再依次比较每个指针当前指向节点的值的大小再进行接下来的拼接操作,分析易得这种方法的时间复杂度为 O ( k n ) O(kn) O(kn)。

2.我们容易注意到上述主要的操作是每次比较并移动指针,且移动的是当前指向节点的值为最小的指针 ,基于以上特点我们可以想到利用最小堆来完成该操作。

解题方法

1.编写内部类QElement。后续创建的最小堆中存储的为指针类型的变量

2.创建最小堆,起初将每个链表头节节点添加进去生成一个最小堆

3.创建虚拟头节点和尾指针以便生成结果链表

4.当最小堆不为空时,每次取出堆顶元素(为ListNode类型指针)当栈顶元素的next指针不为空时,将其next指针指向的节点再次添加到最小堆中,生成一个新的最小堆。

复杂度

时间复杂度:

O ( k l o g n ) O(klogn) O(klogn)

空间复杂度:

O ( k ) O(k) O(k)

Code

java 复制代码
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    private class QElement {
        ListNode curNode;

        public QElement(ListNode curNode) {
            this.curNode = curNode;
        }
    }

    /**
     * 利用小顶堆合并k个升序链表
     *
     * @param lists 链表头节点数组
     * @return ListNode
     */
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) {
            return null;
        }
        int len = lists.length;
        ;
        //创建小顶堆
        PriorityQueue<QElement> minQueue = new PriorityQueue<>(new Comparator<QElement>() {
            @Override
            public int compare(QElement o1, QElement o2) {
                return o1.curNode.val - o2.curNode.val;
            }
        });
        //将链表加入到小顶堆
        for (int i = 0; i < len; ++i) {
            if (lists[i] != null) {
                minQueue.offer(new QElement(lists[i]));
            }
        }
        //创建虚拟头节点
        ListNode dummyNode = new ListNode();
        ListNode tail = dummyNode;
        //当小顶堆不为空时,每次取出堆顶元素添加到结果链表
        while (!minQueue.isEmpty()) {
            QElement element = minQueue.poll();
            ListNode curNode = element.curNode;
            tail.next = element.curNode;
            tail = tail.next;
            //当前指针(已经移动后的指针)指向的的下一位不为空
            if (curNode.next != null) {
                minQueue.offer(new QElement(curNode.next));
            }
        }
        return dummyNode.next;
    }
}
相关推荐
考虑考虑7 小时前
Mybatis实现批量插入
java·后端·mybatis
咖啡八杯8 小时前
GoF设计模式——中介者模式
java·后端·spring·设计模式
青石路12 小时前
记一次多JDK版本问题的排查,一坑套一坑,差点没爬上来
java
像我这样帅的人丶你还15 小时前
Java 后端详解(五):Redis 缓存
java·后端·全栈
plainGeekDev17 小时前
GreenDAO → Room
android·java·kotlin
亦暖筑序1 天前
Java 8老系统AI Workflow实战:把一次性AI对话升级成可恢复工作流
java·后端
敲代码的彭于晏1 天前
Bean 生命周期完全图解:前端同学也能看懂的 Spring 核心机制
java·前端·后端
plainGeekDev1 天前
ButterKnife → ViewBinding
android·java·kotlin
像我这样帅的人丶你还2 天前
Java 后端详解(四):分页与搜索
java·javascript·后端
她的男孩2 天前
数据权限为什么不能只靠注解?Forge 的 Mapper 层 SQL 改写源码拆解
java·后端·架构