【C++】LeetCode:LCR 078. 合并 K 个升序链表

题干:

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

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

解法:优先队列

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
 auto cmp = [](ListNode*a,ListNode*b){
    return a->val>b->val;
};
class Solution {
public:
         ListNode * mergeTwoLists(ListNode * a,ListNode * b){
            ListNode * dummy = new ListNode(0);
            ListNode * cur = dummy;
            while (a!= nullptr&&b!= nullptr){
                if (a->val<b->val){
                    cur->next = a;
                    a = a->next;
                } else{
                    cur->next = b;
                    b = b->next;
                }
                cur = cur->next;
            }
            cur->next = (a== nullptr)?b:a;
            return dummy->next;
        };

        ListNode *mergeKLists(std::vector<ListNode*>& lists){

            std::priority_queue<ListNode*,std::vector<ListNode*>, decltype(cmp)> minHeap(cmp);

            for (auto list:lists) {
                if(list!= nullptr){
                    minHeap.push(list);
                }
            }

            ListNode dummy = ListNode(0);
            ListNode * tail = &dummy;

            while (!minHeap.empty()){
                ListNode * miniNode = minHeap.top();
                minHeap.pop();

                tail->next = miniNode;
                tail = tail->next;

                if (miniNode->next!= nullptr){
                    minHeap.push(miniNode->next);
                }
            }
            return  dummy.next;
        };
};

举例分步解析:

示例:合并三个升序链表

假设我们有三个升序链表:

  1. 链表 11 -> 4 -> 5
  2. 链表 21 -> 3 -> 4
  3. 链表 32 -> 6

初始化状态:

最小堆的基本概念

  • 最小堆 是一种特殊的二叉树结构,其中每个节点的值都小于或等于其子节点的值。
  • 堆顶(即根节点)是整个堆中最小的元素。
  • 最小堆通常用于实现优先队列,因为它可以在 O(log n) 时间内插入和删除元素,并且可以在 O(1) 时间内访问最小元素。

我们的目标是将这三个链表合并成一个升序链表。为了实现这一点,我们可以使用最小堆来高效地找到当前所有链表中值最小的节点。

初始状态

在开始时,我们将每个链表的头节点加入最小堆。此时,最小堆的状态如下:

  • 堆顶 是 1,它来自链表 1 或链表 2(因为我们有两个 1)。
  • 堆的其他节点分别是链表 2 的头节点 1 和链表 3 的头节点 2
第一步:取出堆顶元素

我们从堆中取出最小的元素 1(来自链表 1),并将其加入结果链表。然后,我们将链表 1 的下一个节点 4 加入堆中。此时,堆的状态变为:

  • 堆顶 现在是 1,它来自链表 2。
  • 堆的其他节点分别是链表 1 的下一个节点 4 和链表 3 的头节点 2
第二步:再次取出堆顶元素

我们从堆中取出最小的元素 1(来自链表 2),并将其加入结果链表。然后,我们将链表 2 的下一个节点 3 加入堆中。此时,堆的状态变为:

  • 堆顶 现在是 2,它来自链表 3。
  • 堆的其他节点分别是链表 1 的下一个节点 4 和链表 2 的下一个节点 3
第三步:继续取出堆顶元素

我们从堆中取出最小的元素 2(来自链表 3),并将其加入结果链表。然后,我们将链表 3 的下一个节点 6 加入堆中。此时,堆的状态变为:

  • 堆顶 现在是 3,它来自链表 2。
  • 堆的其他节点分别是链表 1 的下一个节点 4 和链表 3 的下一个节点 6
第四步:继续取出堆顶元素

我们从堆中取出最小的元素 3(来自链表 2),并将其加入结果链表。然后,我们将链表 2 的下一个节点 4 加入堆中。此时,堆的状态变为:

  • 堆顶 现在是 4,它来自链表 1。
  • 堆的其他节点分别是链表 2 的下一个节点 4 和链表 3 的下一个节点 6
第五步:继续取出堆顶元素

我们从堆中取出最小的元素 4(来自链表 1),并将其加入结果链表。堆的状态变为:

  • 堆顶 现在是 4,它来自链表 2。
  • 堆的其他节点是链表1的下一节点5,链表 3 的下一个节点 6
第六步:继续取出堆顶元素

我们从堆中取出最小的元素 4(来自链表 2),并将其加入结果链表。此时,链表 2 已经遍历完毕,没有更多的节点可以加入堆中。

堆的状态变为:堆顶 现在是 5,它来自链表 1,其他节点是6来自链表3。

第七步:继续取出堆顶元素

我们从堆中取出元素 5,并将其加入结果链表。

第八步:继续取出堆顶元素

我们从堆中取出元素 6,并将其加入结果链表。

最终结果

合并后的链表为:1 -> 1 -> 2 -> 3 -> 4 -> 4 -> 5 -> 6

时间复杂度分析

初始化最小堆
  • 操作:将 k 个链表的头节点插入最小堆。
  • 复杂度:每次插入操作的时间复杂度是 O(log⁡k),因此初始化堆的时间复杂度为 O(klog⁡k)。
提取最小元素和插入新元素
  • 操作:每次从堆中提取最小元素并插入新的节点。
  • 复杂度:每次提取最小元素和插入新元素的操作时间复杂度均为 O(log⁡k)。
  • 次数:总共需要进行 N 次提取和插入操作(因为总共有 N 个节点)。
  • 总复杂度:O(Nlog⁡k)

总时间复杂度

  • 初始化堆:O(klog⁡k)
  • 提取和插入操作:O(Nlog⁡k)

因此,总的时间复杂度为: O(klog⁡k+Nlog⁡k)

由于 klog⁡k在大多数情况下远小于 Nlog⁡k,通常可以简化为: O(Nlog⁡k)

空间复杂度分析

  • 最小堆:堆中最多包含 k 个节点(即每个链表的当前最小节点)。
  • 结果链表:需要额外的空间来存储合并后的链表,但这是输出的一部分,不计入额外空间复杂度。

因此,空间复杂度主要由最小堆决定,为: O(k)

总结

  • 时间复杂度:O(Nlog⁡k)
  • 空间复杂度:O(k)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/934160.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用PHPUnit使用本地调试代替远程调试,快速提高开发效率

Laravel 是一个在 Linux 环境下表现非常出色的 PHP 框架&#xff0c;但它在 Windows 环境下可能会遇到一些兼容性和配置问题。为了调试或没试的方便可以在 Windows 环境下进行 Laravel PHPUnit进行本地调试和测试。 本地主要针对断点调试效果非常高效。 在 Laravel 中&#x…

【模型对比】ChatGPT vs Kimi vs 文心一言那个更好用?数据详细解析,找出最适合你的AI辅助工具!

在这个人工智能迅猛发展的时代&#xff0c;AI聊天助手已经深入我们的工作与生活。你是否曾在选择使用ChatGPT、Kimi或是百度的文心一言时感到一头雾水&#xff1f;每款AI都有其独特的魅力与优势&#xff0c;那么&#xff0c;究竟哪一款AI聊天助手最适合你呢&#xff1f;本文将带…

Spring Boot 性能提升的核武器,速度提升 500%!

虚拟线程是 Java 21 引入的一个新特性&#xff0c;用于简化并发编程。它与传统的操作系统线程相比&#xff0c;具有显著的优势&#xff1a; 轻量级&#xff1a;虚拟线程由 JVM 管理&#xff0c;而非操作系统&#xff0c;因此它们的内存占用和创建成本远低于传统线程。理论上&am…

Ubuntu下的gpt-sovits学习记录1:安装与测试

GitCode - 全球开发者的开源社区,开源代码托管平台 国内镜像点。 下载压包&#xff1a; 解压到没有中文名的文件夹内。如我 1.创建虚拟环境 conda create -n GPTSoVits python3.9 2.新建工程 3.部分环境 pip install -r requirements.txt 4.模型下载。建议直接下载上边的…

二叉树节点相关算法题|双分支节点个数|所有左叶子之和|每一层节点平均值(C)

双分支节点个数 假设二叉树采用二叉链表存储结构存储&#xff0c;试设计一个算法&#xff0c;计算一棵给定二叉树的所有双分支节点个数 算法思想 计算一棵二叉树中所有双分支节点个数的递归模型 若树为空&#xff0c;结果为0 若当前节点为双分支节点&#xff0c;递归左右孩子…

MySQL:表的内置函数

目录 一. 日期函数 二. 字符串函数 三. 数学函数​编辑 四. 其他函数 此篇博客讲解MySQL中关于表的内置函数。内置函数广泛用于数据库查询语句中。 一. 日期函数 例子一&#xff1a;创建一个样例表&#xff1a; 类似于隐式转换&#xff0c;虽然这样可以但是不建议。 …

Vue框架入门

Author&#xff1a;Dawn_T17?? 目录 什么是框架 一.Vue 的使用方向 二.Vue 框架的使用场景 &#xff08;TIP&#xff09;MVVM思想 三.Vue入门案例 TIP&#xff1a;插值表达式 四.Vue-指令? &#xff08;1&#xff09;v-bind 和 v-model? ? &#xff08;2&#x…

【OpenCV】图像转换

理论 傅立叶变换用于分析各种滤波器的频率特性。对于图像&#xff0c;使用 2D离散傅里叶变换&#xff08;DFT&#xff09; 查找频域。快速算法称为 快速傅立叶变换&#xff08;FFT&#xff09; 用于计算DFT。 Numpy中的傅立叶变换 首先&#xff0c;我们将看到如何使用Numpy查…

Nanolog起步笔记-10-log解压过程(4)寻找meta续2

Nanolog起步笔记-10-log解压过程4寻找meta续2 写在前面重新开始trace 写在前面 前面的工作&#xff0c;已做打下令人有信心的基础。 重新开始trace 之前我们起步就看到了 metadata &#xff0c;显然这前就已加载了。 所以&#xff0c;只需要重走一遍代码&#xff0c;就能得到…

Vue3+Node中使用webrtc推流至mediamtx

前言 项目的 Web 端是 Vue3 框架&#xff0c;后端是 GO 框架。需要实现将客户端的本地摄像头媒体流推送至服务端&#xff0c;而我自己从未有媒体流相关经验&#xff0c;最初 leader 让我尝试通过 RTSP 协议推拉流&#xff0c;我的思路就局限在了 RTSP 方向。 最初使用的服务端…

小程序IOS安全区域优化:safe-area-inset-bottom

ios下边有一个小黑线&#xff0c;位于底部的元素会被黑线阻挡 safe-area-inset-bottom 一 用法及作用&#xff1a; IOS全面屏底部有小黑线&#xff0c;位于底部的元素会被黑线阻挡&#xff0c;可以使用以下样式&#xff1a; .model{padding-bottom: constant(safe-area-ins…

NVR小程序接入平台EasyNVR国标协议接入无告警是什么原因?

在现代视频监控系统中&#xff0c;国标接入已成为一种重要的技术标准&#xff0c;尤其是在GB28181协议的推动下&#xff0c;这一标准被广泛应用于安防设备的统一接入和管理。国标接入不仅提高了设备间的互联互通能力&#xff0c;还为用户提供了更高效、更智能的视频监控解决方案…

在CSDN设置“关注博主即可阅读全文”

我们在平时CSDN上搜索文章&#xff0c;打开文章&#xff0c;需要关注博主方可继续阅读的&#xff0c;相必有人会很困惑&#xff0c;也有人会觉得很烦。一般选择先关注&#xff0c;看完取消关注&#xff0c;不管怎么说&#xff0c;今天我来教大家如何设置“关注博主即可阅读全文…

《AI行政管理:开启高效治理新时代》

一、引言 AI 行政管理能力的定义和重要性 AI 行政管理能力是指人工智能在行政管理领域的应用能力。它涵盖了多个方面&#xff0c;包括政府决策支持、公共服务优化、行政流程自动化、社会治理与公共安全以及政府内部管理等。在当今时代&#xff0c;AI 行政管理能力具有至关重要…

`yarn list --pattern element-ui` 是一个 Yarn 命令,用于列出项目中符合指定模式(`element-ui`)的依赖包信息

文章目录 命令解析&#xff1a;功能说明&#xff1a;示例输出&#xff1a;使用场景&#xff1a; yarn list --pattern element-ui 是一个 Yarn 命令&#xff0c;用于列出项目中符合指定模式&#xff08; element-ui&#xff09;的依赖包信息。 命令解析&#xff1a; yarn list…

Vue前端实现预览并打印PDF文档

一. 需求 1. 点击文档列表中的【打印】按钮&#xff0c;获取后台生成的PDF的url&#xff0c;弹窗进行预览&#xff1a; 2. 点击【打印】按钮&#xff0c;进行打印预览和打印&#xff1a; 二. 需求实现 首先后台给的是word文档&#xff0c;研究了一圈后发现暂时无法实现&…

【开源】A066—基于JavaWeb的农产品直卖平台的设计与实现

&#x1f64a;作者简介&#xff1a;在校研究生&#xff0c;拥有计算机专业的研究生开发团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看项目链接获取⬇️&#xff0c;记得注明来意哦~&#x1f339; 赠送计算机毕业设计600个选题ex…

MR20一体式IO 在3C领域的应用

一、导读 该公司成立于1999年&#xff0c;是中国最早专注于泛半导体产业的投资机构&#xff0c;于2015年在 新三板上市。是集研发&#xff0c;制造&#xff0c;销售&#xff0c;服务于一体的国家级高新技术企业&#xff0c;致力于提供暖通空调及供热采暖 控制为核心的产品、技…

Conda + JuiceFS :增强 AI 开发环境共享能力

Conda 是当前 AI 应用开发领域中非常流行的环境和包管理系统&#xff0c;因其能够简单便捷地创建与系统资源相隔离的虚拟环境广受欢迎。 Conda 支持在不同的操作系统上重建相同的工作环境&#xff0c;但在环境共享复用方面仍存在一些挑战。比如&#xff0c;在不同机器上复用相…

【推荐算法】单目标精排模型——FiBiNET

key word: 学术论文 Motivation&#xff1a; 传统的Embedding&MLP算法是通过内积和Hadamard product实现特征交互的&#xff0c;这篇文章的作者提出了采用SENET实现动态学习特征的重要性&#xff1b;作者认为简单的内积和Hadamard product无法有效对稀疏特征进行特征交互&a…