力扣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;
    }
}
相关推荐
0+1116 分钟前
算法 --链表
数据结构·算法·leetcode·链表
geats人山人海9 分钟前
java 4继承
java·开发语言
圣保罗的大教堂17 分钟前
leetcode 2333. 最小差值平方和 中等
leetcode
众链网络32 分钟前
Agent 的成本大头不在“写“,在“判断“:拆解专用决策模型的三层架构
java·开发语言·人工智能·微服务
周小董35 分钟前
[1371]jdk管理工具
java·开发语言
青春逝如流水1 小时前
Java 中线程的创建方式:从基础到现代
java·开发语言·多线程·ai文章
Peregrine91 小时前
C++ - > 类和对象
java·c++·算法
2501_933923252 小时前
SpringCloud组件:Eureka服务注册与发现
java·开发语言·后端·spring cloud·eureka
Wang's Blog2 小时前
Java 中间件之 RabbitMQ 快速入门: SpringAMQP 消息转换器
java·中间件·java-rabbitmq
Re_zero2 小时前
一次 SSE 断流排查:PrintWriter 吞掉了我的 IOException
java·后端