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

Leetcode二十三题:合并K个升序链表【22/1000 python】

“合并K个升序链表”,这是一道中等难度的题目,经常出现在编程面试中。以下是该问题的详细描述、解题步骤、不同算法的比较、代码示例及其分析。

问题描述

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

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

示例:

输入:lists = [[1,4,5],[1,3,4],[2,6]]输出:[1,1,2,3,4,4,5,6]

解释:链表数组如下:

[1->4->5,1->3->4,2->6
]将它们合并到一个有序链表中得到。1->1->2->3->4->4->5->6

方法一:直接合并

解题步骤

  1. 初始化:
    • 如果链表数组为空,则返回None。
    • 如果链表数组中只有一个链表,则直接返回这个链表。
  2. 逐对合并链表:
    • 初始化merged_list为lists[0],即从第一个链表开始。
    • 逐个遍历余下的链表,与merged_list进行合并,每次合并后更新merged_list。
  3. 合并两个链表的函数:
    • 创建一个哑结点dummy作为合并链表的起始节点。
    • 使用两个指针分别指向两个链表的头部,比较指针所指节点的值,将较小值节点连接到结果链表上,然后移动该指针到下一个节点。
    • 如果某一链表遍历完毕,将另一链表的剩余部分直接连接到结果链表的尾部。
    • 返回哑结点的下一个节点,即合并后链表的头部。
  4. 完成合并:
    • 继续遍历并合并剩余的链表,直至所有链表均合并完成。

代码示例

class ListNode:def __init__(self, val=0, next=None):self.val = valself.next = nextdef mergeTwoLists(l1: ListNode, l2: ListNode) -> ListNode:dummy = ListNode(0)current = dummywhile l1 and l2:if l1.val < l2.val:current.next = l1l1 = l1.nextelse:current.next = l2l2 = l2.nextcurrent = current.next# Attach the remaining part of l1 or l2current.next = l1 if l1 is not None else l2return dummy.nextdef mergeKLists(lists: List[Optional[ListNode]]) -> Optional[ListNode]:if not lists:return Noneif len(lists) == 1:return lists[0]merged_list = lists[0]for i in range(1, len(lists)):merged_list = mergeTwoLists(merged_list, lists[i])return merged_list

性能分析

时间复杂度:对于k个链表的情况,直接合并的时间复杂度是O(kN),其中N是链表中的节点总数。这是因为每次合并操作需要遍历涉及的两个链表的长度,而链表长度随着合并次数增加而增长。
空间复杂度:O(1),不计入输入和输出占用的空间,合并过程中只使用了常数额外空间。

结论

直接合并是一个简单直观的方法,适合链表数量较少或对时间复杂度要求不是非常严格的情况。然而,对于大量链表的合并,使用最小堆或分治法(如两两合并)可能会更高效。

方法二:使用最小堆

解题步骤

  1. 初始化最小堆
    • 创建一个空的最小堆(优先队列)来存储链表节点,堆中的元素按节点的值排序。
    • 遍历所有链表,将每个链表的头节点加入最小堆中。
  2. 构建结果链表
    • 创建一个哑结点(dummy node)作为结果链表的头部,这样可以方便地添加新节点。
    • 使用一个指针current跟踪结果链表的最后一个节点。
  3. 遍历并合并
    • 当最小堆不为空时,执行以下操作:
    • 从堆中弹出最小元素(当前最小节点)。
    • 将current的next指针指向这个最小节点。
    • 移动current指针到最小节点。
    • 如果这个最小节点有后继节点,则将后继节点加入最小堆中。
  4. 完成合并
    • 当最小堆为空时,所有链表的节点都已链接到结果链表中。
    • 返回哑结点的next,即合并后链表的头部。

代码示例

import heapqclass ListNode:def __init__(self, val=0, next=None):self.val = valself.next = nextdef mergeKLists(lists):if not lists:return None# Create a heap and a dummy node to start the merged listheap = []dummy = ListNode(0)current = dummy# Initial population of the heap with the first node of each list, if availablefor i, node in enumerate(lists):if node:heapq.heappush(heap, (node.val, i, node))# Iterate over the heap and build the merged listwhile heap:val, idx, node = heapq.heappop(heap)current.next = nodecurrent = current.nextif node.next:heapq.heappush(heap, (node.next.val, idx, node.next))return dummy.next

性能分析

时间复杂度:每个节点被处理一次,而且每次处理涉及的时间复杂度为O(log k),因此总的时间复杂度是O(Nlogk),其中是所有链表中元素的总数,是链表的数量。
空间复杂度:最小堆中最多存储个元素,因此空间复杂度是O(k)。

结论

使用最小堆的方法在合并多个链表时非常有效,尤其是当链表数量较多时。这种方法的时间复杂度相对较低,是因为它能快速地找到当前最小的节点并将其加入到结果链表中,而空间复杂度则主要由堆的大小决定。这使得最小堆方法在处理大规模数据时表现出色。

方法三:分治合并

解题步骤

  1. 递归分治函数定义
    • 创建一个函数mergeKLists,如果列表为空或长度为1,直接返回。
    • 如果列表长度大于1,将链表列表分成两半,分别对这两半递归调用mergeKLists。
  2. 合并两个链表的函数
    • 创建另一个辅助函数mergeTwoLists用于合并两个链表。这个函数将两个链表头作为输入,合并后返回新链表的头。
  3. 执行分治合并
    • 在mergeKLists中,通过递归地将链表数组拆分至只剩单个链表,然后开始合并。
    • 使用mergeTwoLists逐对合并链表,直至整个数组合并为一个链表。
  4. 返回结果
    • 递归完全执行完毕后,返回合并后的链表头部。

代码示例

class ListNode:def __init__(self, val=0, next=None):self.val = valself.next = nextdef mergeTwoLists(l1: ListNode, l2: ListNode) -> ListNode:if not l1 or not l2:return l1 or l2dummy = ListNode(0)current = dummywhile l1 and l2:if l1.val < l2.val:current.next = l1l1 = l1.nextelse:current.next = l2l2 = l2.nextcurrent = current.nextcurrent.next = l1 or l2return dummy.nextdef mergeKLists(lists: List[ListNode]) -> ListNode:if not lists:return Noneif len(lists) == 1:return lists[0]mid = len(lists) // 2left = mergeKLists(lists[:mid])right = mergeKLists(lists[mid:])return mergeTwoLists(left, right)

性能分析

时间复杂度
• 每次合并操作需要线性时间,即O(n),其中n是参与合并的两个链表的总节点数。
• 通过每次递归减半链表数组的长度,整体上每层递归需要O(N)时间,其中N是所有链表中元素的总数。
• 递归的深度是O(log k),因此总的时间复杂度是O(N logk)。
空间复杂度
• 递归调用栈的深度为O(logk),因此空间复杂度为O(logk)。

结论

分治合并是解决合并多个链表的问题中非常有效的方法,尤其适合处理大量链表的情况。它的时间复杂度与使用最小堆的方法相同,但通常在实际应用中由于常数因子较小而表现更优。此外,分治法的代码结构清晰,易于理解和实现,使其成为面试和实际工程中的常用策略。

总结

在这里插入图片描述
合并 K 个升序链表可以通过多种算法实现,包括直接合并、使用最小堆和分治合并。在面试中,根据具体情况选择最适合的方法。其中,使用最小堆和分治合并的方法因其较优的时间复杂度通常更受青睐。这些方法不仅展示了数据结构的有效使用,也体现了分治策略在实际问题中的应用。

相关文章:

Leetcode二十三题:合并K个升序链表【22/1000 python】

“合并K个升序链表”&#xff0c;这是一道中等难度的题目&#xff0c;经常出现在编程面试中。以下是该问题的详细描述、解题步骤、不同算法的比较、代码示例及其分析。 问题描述 给你一个链表数组&#xff0c;每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中…...

03-echarts如何画立体柱状图

echarts如何画立体柱状图 一、创建盒子1、创建盒子2、初始化盒子&#xff08;先绘制一个基本的二维柱状图的样式&#xff09;1、创建一个初始化图表的方法2、在mounted中调用这个方法3、在方法中写options和绘制图形 二、画图前知识1、坐标2、柱状图图解分析 三、构建方法1、创…...

2024蓝桥A组E题

成绩统计 问题描述格式输入格式输出样例输入样例输出评测用例规模与约定解析参考程序难度等级 问题描述 题目有问题方差定义那加平方&#xff08;vi-v&#xff09; 格式输入 输入的第一行包含三个正整数n,k,T &#xff0c;相邻整数之间使用一个空格分隔。 第二行包含n个正整数…...

Java单例模式

单例模式 什么是单例模式介绍实现单例模式的几种实现方式1. 懒汉式&#xff0c;线程不安全2、懒汉式&#xff0c;线程安全3、饿汉式4、双检锁/双重校验锁&#xff08;DCL&#xff0c;即 double-checked locking&#xff09;5、登记式/静态内部类6、枚举 什么是单例模式 单例模…...

04—常用方法和正则表达式

一、字符串 1.length 属性返回字符串的长度(字符数)。 2.在字符串中查找字符串 indexOf() 字符串使用 indexOf() 来定位字符串中某一个指定的字符首次出现的位置 如果没找到对应的字符函数返回-1 lastIndexOf() 方法在字符串末尾开始查找字符串出现的位置。 3.replace() 方…...

Python异常处理机制详解及示例

Python异常处理机制详解及示例 在编程过程中&#xff0c;异常处理是一项至关重要的技能。Python作为一种功能强大的编程语言&#xff0c;提供了一套完善的异常处理机制&#xff0c;使得程序在遇到错误或异常情况时能够优雅地处理&#xff0c;而不是直接崩溃。本文将详细介绍Py…...

解决:Java后端返回给前端的Date格式数据相差8小时的问题

问题描述&#xff1a; 后端得到的数据是对的&#xff0c;但是返回给前端后&#xff0c;数据比原数据慢了8小时。 原因&#xff1a; json数据在返回浏览器端是会被spring-boot默认的Jackson框架转换&#xff0c;而Jackson框架默认的时区GMT&#xff08;相对于中国是少了8小时…...

linux安装weblogic

版本 Linux: Red Hat Enterprise Linux Server 6.9 64bit(安装了图形界面) JDK: 1.8U361 64bit weblogic: fmw_14.1.1.0.0_wls.jar 安装手顺 安装配置JDK 下载jdk压缩包 下载取得jdk-8I361-linux-x64.tar.gz将压缩包放置到linux,并解压缩到指定目录tar xvf jdk-8u201-…...

Unity WebGL Release-Notes

&#x1f308;WebGL Release-Notes 收集的最近几年 Unity各个版本中 WebGL的更新内容 &#x1f4a1;WebGL Release-Notes 2023 &#x1f4a1;WebGL Release-Notes 2022 &#x1f4a1;WebGL Release-Notes 2021 &#x1f4a1;WebGL Release-Notes 2020...

Excel 记录单 快速录入数据

一. 调出记录单 ⏹记录单功能默认是隐藏的&#xff0c;通过如下如图所示的方式&#xff0c;将记录单功能显示出来。 二. 录入数据 ⏹先在表格中录入一行数据&#xff0c;给记录单一个参考 ⏹将光标至于表格右上角&#xff0c;然后点击记录单按钮&#xff0c;调出记录单 然后点…...

go 利用channel实现定时任务

package mainimport ("fmt""net/http""time" )func main() {// 创建一个定时器&#xff0c;每隔1秒钟执行一次ticker : time.NewTicker(1 * time.Second)done : make(chan bool)//设置3s超时&#xff0c;避免请求时间过长client : http.Client{T…...

JWT介绍

JWT JSON Web Token (JWT) 是一种开放标准 (RFC 7519)&#xff0c;提供一种简洁且自包含的方式&#xff0c;以JSON形式在通信双方间传递信息。这些信息可通过数字签名进行验证&#xff0c;确保其可信度。JWT 可以使用密钥&#xff08;HMAC&#xff09;或 RSA 或 ECDSA 的公钥/…...

如何实现YOLOv8保存目标检测后的视频文件

首先安装所需的库和依赖项&#xff0c;确保你已经安装了OpenCV和YOLOv8的相关库和依赖项。你可以使用pip或conda来安装它们。 其次加载YOLOv8模型&#xff0c;使用YOLOv8的训练权重文件和配置文件&#xff0c;加载模型并进行初始化。这可以通过使用适当的库函数来完成&…...

LlamaIndex 组件 - Prompts

文章目录 一、关于 Prompts1、概念2、使用模式概览3、示例指南 二、使用模式1、定义自定义提示2、获取和设置自定义提示2.1 常用提示2.2 访问提示2.3 更新提示2.4 修改查询引擎中使用的提示2.5 修改索引构建中使用的提示 3、[高级]高级提示功能3.1 部分格式化3.2 模板变量映射3…...

Github 2024-04-16Python开源项目日报 Top10

根据Github Trendings的统计,今日(2024-04-16统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目10TypeScript项目1Vue项目1系统设计指南 创建周期:2507 天开发语言:Python协议类型:OtherStar数量:241693 个Fork数量:42010 次…...

ElasticSearch nested 字段多关键字搜索,高亮全部匹配关键字的处理

ElasticSearch nested 字段多关键字搜索&#xff0c;高亮全部匹配关键字的处理 环境介绍 ElasticSearch 版本号: 6.7.0 需求说明 用户会传入多个关键字去ES查询ElasticSearch nested 字段 的多个字段&#xff0c;要求在返回的结果中被搜索的字段需要高亮所有匹配的关键字。…...

python_31-32

目录 1.进程 2.同步进程&#xff1a; 3.守护进程&#xff1a; 1.进程 # ### 进程 process import os,time""" # ps -aux 查看进程号 # ps -aux | grep 2784 过滤查找2784这个进程# 强制杀死进程 kill -9 进程号# 获取当前进程号 res os.getpid() print(res)…...

关于机器学习/深度学习的一些事-答知乎问(四)

如何评估和量化深度学习的可解释性问题&#xff1f; 针对深度学习模型&#xff0c;评估指标能够全面衡量模型是否满足可解释性。与分类的评估指标&#xff08;准确度、精确度和召回率&#xff09;一样&#xff0c;模型可解释性的评估指标应能从特定角度证明模型的性能。但是&a…...

[spring] Spring Boot REST API - 项目实现

Spring Boot REST API - 项目实现 书接上文 Spring Boot REST API - CRUD 操作&#xff0c;一些和数据库相关联的注解在 [spring] spring jpa - hibernate CRUD 主要的 layer 如下&#xff1a; #mermaid-svg-QE1PR1gyrkz4XIT0 {font-family:"trebuchet ms",verdana…...

ELK之Filebeat实用配置及批量部署(部署200+可用)

跟我之前Zabbix-agent批量部署脚本Linux and Windows&#xff08;部署300可用&#xff09;文章的套路一样&#xff0c;在使用该脚本前&#xff0c;请先准备好安装包及配置好安装包的资源下载点&#xff0c;由于我这边是纯内网&#xff0c;所以我就找了一个NAS做了共享目录&…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...