当前位置: 首页 > article >正文

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

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

文章目录

  • 题目描述
  • 思路
  • 解题方法
  • 复杂度
  • Code

题目描述

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

请你将所有链表合并到一个升序链表中,返回合并后的链表。
在这里插入图片描述
在这里插入图片描述

思路

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

/**
 * 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;
    }
}

http://www.kler.cn/a/148296.html

相关文章:

  • OpenGL ES 共享上下文实现多线程渲染
  • 【前端】Vue中如何避免出现内存泄漏
  • 基于迭代重加权最小二乘法的算法及例程
  • gdb编译教程(支持linux下X86和ARM架构)
  • 知识库管理系统:企业数字化转型的加速器
  • AI 扩展开发者思维方式:以 SQL 查询优化为例
  • vivado产生报告阅读分析27
  • 前端相关免查整合-vue、es、工具类等
  • 计算机丢失vcomp140.dll是什么意思,如何解决与修复(附教程)
  • 代码随想录算法训练营 ---第四十二天
  • ubuntu 使用快照启动polygon主网
  • C语言——数组转换
  • 野火霸天虎 STM32F407 学习笔记(六)系统时钟详解
  • 亚信科技AntDB数据库与库瀚存储方案完成兼容性互认证
  • frp内网穿透
  • 4-docker-compose介绍(部署flask案例、yaml文件、启动)、新建flask项目、编写Dockerfile(用于构建flask项目的镜像)、
  • 头发的方向图(2D和3D)与合成
  • 【Mybatis】预编译/即时sql 数据库连接池
  • linux进入telnet和推出telnet
  • 零基础在ubuntu上搭建rtmp服务器-srs
  • 关于Redis底层的两个问题
  • 18、Android 组件化
  • C++中的map和set的使用
  • 【Spark入门】基础入门
  • facebook引流软件需要具备什么功能
  • 相关性分析和作图