力扣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;
    }
}
相关推荐
极客先躯14 分钟前
高级java每日一道面试题-2025年3月22日-微服务篇[Nacos篇]-Nacos的主要功能有哪些?
java·开发语言·微服务
爱喝醋的雷达24 分钟前
Spring SpringBoot 细节总结
java·spring boot·spring
SsummerC33 分钟前
【leetcode100】每日温度
数据结构·python·leetcode
jingshaoyou34 分钟前
Strongswan linked_list_t链表 注释可独立运行测试
数据结构·链表·网络安全·list
Swift社区1 小时前
Swift LeetCode 246 题解:中心对称数(Strobogrammatic Number)
开发语言·leetcode·swift
coderzpw1 小时前
当模板方法模式遇上工厂模式:一道优雅的烹饪架构设计
java·模板方法模式
直裾1 小时前
Mapreduce初使用
java·mapreduce
悠夏安末2 小时前
intellij Idea 和 dataGrip下载和安装教程
java·ide·intellij-idea
suimeng62 小时前
ChromeDriver的常用方法
java·selenium
Hellyc2 小时前
SpringMVC响应数据:页面跳转与回写数据
java·前端·学习