【LeetCode 热题 100】23. 合并 K 个升序链表——(解法一)逐一合并

Problem: 23. 合并 K 个升序链表
题目:给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。

文章目录

  • 整体思路
  • 完整代码
  • 时空复杂度
    • 时间复杂度:O(K * N)
    • 空间复杂度:O(1)

整体思路

这段代码旨在解决一个经典的链表问题:合并 K 个排序链表 (Merge K Sorted Lists)。问题要求将一个包含 K 个已排序链表的数组,合并成一个单一的、大的有序链表。

该实现采用了一种简单直接的 逐一合并 (One by One Merging) 的策略。它将“合并K个链表”的问题,简化为了“重复执行 K-1 次‘合并两个链表’”的问题。

其核心逻辑步骤如下:

  1. 处理边界情况

    • 首先,检查输入的链表数组 lists 是否为 null 或空。如果是,直接返回 null
    • 如果数组中只有一个链表,直接返回该链表。
  2. 迭代合并

    • 算法将 lists[0] 作为“累加器”或“基准链表”。
    • 通过一个 for 循环,从 i=1 开始,依次将 lists[i] 合并到 lists[0] 中。
    • lists[0] = merge(lists[0], lists[i]); 这一行是核心。它调用一个辅助函数 merge,将当前的合并结果 lists[0] 与下一个链表 lists[i] 进行合并,然后用新的、更长的合并结果来更新 lists[0]
    • 这个过程会重复 K-1 次。
  3. merge 辅助函数

    • 这个私有函数 merge(l1, l2) 是一个标准的“合并两个有序链表”的实现。
    • 它使用哨兵节点 dummy 和一个 cur 指针,通过迭代比较 l1l2 的节点值,将较小的节点链接到结果链表的末尾,直到其中一个链表被遍历完。
    • 最后,将另一个链表中剩余的部分直接追加到结果链表的末尾。
    • 这个函数在每次主循环中被调用。
  4. 返回结果

    • for 循环结束后,lists[0] 中就存储了所有 K 个链表合并后的最终结果,将其返回。

虽然这个方法逻辑清晰,易于理解,但它并不是最高效的解决方案,因为在合并过程中存在大量的重复比较。

完整代码

/*** Definition for singly-linked list.*/
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 {/*** 合并 K 个排序链表。* @param lists 一个包含 K 个排序链表的数组* @return 合并后的单一排序链表*/public ListNode mergeKLists(ListNode[] lists) {// 处理边界情况:输入为空或没有链表if (null == lists || lists.length == 0) {return null;}int n = lists.length;// 如果只有一个链表,直接返回它if (1 == n) {return lists[0];}// 步骤 1: 逐一合并// 将 lists[0] 作为基础,依次将 lists[1], lists[2], ... 合并进来for (int i = 1; i < n; i++) {// 调用辅助函数合并当前的累积结果 lists[0] 和下一个链表 lists[i]lists[0] = merge(lists[0], lists[i]);}// 循环结束后,lists[0] 就是最终的合并结果return lists[0];}/*** 辅助函数:合并两个有序链表。* @param l1 第一个有序链表* @param l2 第二个有序链表* @return 合并后的有序链表*/private ListNode merge(ListNode l1, ListNode l2) {// 使用哨兵节点简化合并逻辑ListNode dummy = new ListNode();ListNode cur = dummy;// 比较两个链表的节点,将较小的链接到结果链表while (null != l1 && null != l2) {if (l1.val < l2.val) {cur.next = l1;l1 = l1.next;} else {cur.next = l2;l2 = l2.next;}cur = cur.next;}// 将剩余的链表部分直接追加到末尾cur.next = null == l1 ? l2 : l1;return dummy.next;}
}

时空复杂度

时间复杂度:O(K * N)

  1. merge 函数的复杂度:合并两个长度分别为 mn 的链表,时间复杂度是 O(m + n)。
  2. 主循环分析
    • K 是链表的数量,N 是所有链表的节点总数。为简化分析,我们假设每个链表平均有 N/K 个节点。
    • 第一次合并 (i=1): merge(lists[0], lists[1])lists[0] 长度为 N/Klists[1] 长度为 N/K。耗时 O(2N/K)。合并后 lists[0] 长度变为 2N/K
    • 第二次合并 (i=2): merge(lists[0], lists[2])lists[0] 长度为 2N/Klists[2] 长度为 N/K。耗时 O(3N/K)。合并后 lists[0] 长度变为 3N/K
    • i 次合并: lists[0] 长度为 i * (N/K)lists[i] 长度为 N/K。耗时 O((i+1)N/K)。
    • 总时间Σ(i=1 to K-1) (i+1)N/K = (N/K) * Σ(j=2 to K) j = (N/K) * (K(K+1)/2 - 1)
    • 这个表达式的最高阶项是 (N/K) * (K^2 / 2),所以复杂度是 O(N * K)

综合分析
该算法的时间复杂度为 O(N * K),其中 N 是总节点数,K 是链表数。当 K 较大时,这个效率并不理想。

空间复杂度:O(1)

  1. 主要存储开销
    • merge 函数内部使用了 dummycur 等常数个指针变量。
    • 主函数 mergeKLists 也没有使用与 NK 成比例的额外数据结构。它是在原地修改 lists 数组的第一个元素。

综合分析
算法所需的额外辅助空间是常数级别的。因此,其空间复杂度为 O(1)。这是该解法的一个优点。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

垃圾收集器-Serial Old

第一章 引言1.1 JVM 中垃圾收集的简要概述JVM&#xff08;Java Virtual Machine&#xff09;作为 Java 程序的运行时环境&#xff0c;负责将字节码加载至内存并执行&#xff0c;同时也承担着内存管理的重任。垃圾收集&#xff08;Garbage Collection&#xff0c;简称 GC&#x…

Docker(02) Docker-Compose、Dockerfile镜像构建、Portainer

Docker-Compose 1、Docker Desktop 在Windows上安装Docker服务&#xff0c;可以使用Docker Desktop这个应用程序。 下载并安装这样的一个安装包 安装好后&#xff1a;执行命令 docker --version 从Docker Hub提取hello-world映像并运行一个容器&#xff1a; docker run h…

大数据时代UI前端的用户体验设计新思维:以数据为驱动的情感化设计

hello宝子们...我们是艾斯视觉擅长ui设计和前端数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩!一、引言&#xff1a;从 “经验设计” 到 “数据共情” 的体验革命传统 UI 设计常陷入 “设计师主观经…

TypeScript 学习手册

1.TypeScript 概念 TypeScript&#xff08;简称 TS&#xff0c;静态类型&#xff09;是微软公司开发的一种基于 JavaScript &#xff08;简称 JS&#xff0c;动态类型&#xff09;语言的编程语言。TypeScript 可以看成是 JavaScript 的超集&#xff08;superset&#xff09;&a…

掌握现代CSS:变量、变形函数与动态计算

CSS近年来发展迅速&#xff0c;引入了许多强大的功能&#xff0c;如变量、高级变形函数和动态计算能力。本文将深入探讨如何在CSS中设置并使用变量&#xff0c;以及如何有效利用translate3d、translateY和translateX等变形方法。我们还将解析var()和calc()函数的关键作用。一、…

贝尔量子实验设想漏洞

1 0 1 0 1 1 0 1 0 1 1 1 0 0 1 0 带墨镜如果先上下交换再左右交换&#xff0c;很可能不一样的概率是2%&#xff0c;但是因为交换诞生了一个与之前序列相同的所以不一样概率变成1%&#xff0c;我们在测的时候不能这么测啊&#xff0c;你得看序列完…

在 Android 库模块(AAR)中,BuildConfig 默认不会自动生成 VERSION_CODE 和 VERSION_NAME 字段

为什么AAR库模块的 BuildConfig 没有 versionCode 和 versionName&#xff1f; aar库模块的 BuildConfig 默认不包含版本信息 应用模块&#xff08;com.android.application&#xff09;会自动生成 versionCode 和 versionName 到 BuildConfig。但库模块&#xff08;com.androi…

强化学习 (11)随机近似

计算均值的新方法有两种方法。第一种方法很直接&#xff0c;即收集所有样本后计算平均值&#xff1b;但这种方法的缺点是&#xff0c;若样本是在一段时间内逐个收集的&#xff0c;我们必须等到所有样本都收集完毕。第二种方法可避免此缺点&#xff0c;因为它以增量迭代的方式计…

PHP `implode` 深度解析:从基础到高阶实战指南

文章目录一、基础语法与底层原理执行过程解析&#xff1a;二、性能关键&#xff1a;避免隐含陷阱1. 类型转换黑盒2. 大数组内存优化3. 关联数组处理三、高阶应用场景1. SQL语句安全构建2. CSV文件生成3. 模板引擎实现四、多维数组处理方案1. 递归降维2. JSON转换桥接五、性能对…

开发语言中关于面向对象和面向过程的笔记

开发语言中关于面向对象和面向过程的笔记市面主流语言分类面向过程面向对象市面主流语言分类 面向过程编程&#xff08;Procedural Programming&#xff09;&#xff1a;C语言&#xff1b;面向对象编程语言&#xff08;Object-Oriented Programming, OOP&#xff09; &#xf…

AI产品经理面试宝典第3天:技术分层、边界与市场全景系列面试题

面试指导 面试官:请从技术实现效果的角度,解释AI技术分层。 你的回答: AI技术分为三层。 第一层是认知层:通过图像处理、语音识别、自然语言理解等技术,让机器感知环境。比如摄像头识别行人动作,麦克风捕捉用户指令。 第二层是预测层:基于行为数据预判下一步需求。例如…

Intel英特尔ICH7R/ICH8R/ICH9R/ICH10R系列下载地址--intel_msm_8961002 下载 Version 8.9.6.1002

Intel英特尔ICH7R/ICH8R/ICH9R/ICH10R系列下载地址intel_msm_8961002 下载 Version 8.9.6.1002https://xiazai.zol.com.cn/detail/66/653449.shtml通过网盘分享的文件&#xff1a;intel_msm_8961002.zip 链接: https://pan.baidu.com/s/13N9ZLXWkaWaEHQ5P90Jt0g?pwd3790 提取码…

AI(学习笔记第五课) 使用langchain进行AI开发 load documents(web)

文章目录AI(学习笔记第五课) 使用langchain进行AI开发 load documents(web)学习内容&#xff1a;1.load documents&#xff08;web&#xff09;1.1 学习url1.2 提前安装python的package1.2 使用WebBaseLoader进行webpage的load1.3 使用BeautifulSoup4进行webpage的部分截取1.4 …

使用macvlan实现容器的跨主机通信

使用环境&#xff1a; 两台运行docker的服务器 A机器网段&#xff1a;192.168.86.61 B机器网段&#xff1a;192.168.86.62 运行的容器需装有ping指令&#xff0c; 实验参数解释&#xff1a; -d macvlan 指定创建网络驱动类型 --subnet 指定子网范围 -gateway 指定网关地址 -o p…

深度学习_全连接神经网络

1.什么是神经网络神经网络中信息只向一个方向移动&#xff0c;即从输入节点向前移动&#xff0c;通过隐藏节点&#xff0c;再向输出节点移 动&#xff0c;网络中没有循环或者环。其中的基本构件是&#xff1a; 输入层&#xff1a;即输入x的那一层 输出层&#xff1a;即输出y的那…

OpenLayers使用

初学ol&#xff0c;实现了高德地图不同图层的切换、交互性地图飞行以及加载本地JSON数据。说一下不同图层切换的想法&#xff1a;1.对于标准地图和卫星地图&#xff1a;二者最初便挂载到map上&#xff0c;两个图层是叠加显示的&#xff1b;当点击按钮时&#xff0c;其实是使用 …

day4--上传图片、视频

1. 分布式文件系统 1.1 什么是分布式文件系统 文件系统是负责管理和存储文件的系统软件&#xff0c;操作系统通过文件系统提供的接口去存取文件&#xff0c;用户通过操作系统访问磁盘上的文件。 下图指示了文件系统所处的位置&#xff1a; 常见的文件系统&#xff1a;FAT16/FA…

极矢量与轴矢量

物理量分为标量和矢量&#xff0c;矢量又分为极矢量和轴矢量。 矢量是既有大小又有方向并按平行四边形法则相加的量。矢量有极矢量和轴矢量两种&#xff0c;其间的区别是在镜像反射变换下遵循不同的变换规律,许多物理量都是矢量,同样,其中也有极矢量和轴矢量的区分,在力学中,例…

文章发布易优CMS(Eyoucms)网站技巧

为了更快的上手数据采集及发布到易优CMS(eyoucms)网站&#xff0c;特地总结了些新手常常会遇到的操作问题与技巧&#xff0c;如下&#xff1a; 免费易优CMS采集发布插件下载&#xff0c;兼容火车头、八爪鱼、简数采集等 目录 1. 发布到易优CMS指定栏目 2. 发布文章到易优CM…

INA226 数据手册解读

INA226是一款数字电流检测放大器&#xff0c;配备I2C和SMBus兼容接口。该器件可提供数字电流、电压以及功率读数&#xff0c;可灵活配置测量分辨率&#xff0c;并具备连续运行与触发操作模式。该芯片通常由一个单独的电源供电&#xff0c;电压范围为 2.7V 至 5.5V引脚说明​​引…