Python算法题集_合并K个升序链表

 Python算法题集_合并K个升序链表

  • 题23:合并K个升序链表
  • 1. 示例说明
  • 2. 题目解析
    • - 题意分解
    • - 优化思路
    • - 测量工具
  • 3. 代码展开
    • 1) 标准求解【双层循环】
    • 2) 改进版一【列表排序】
    • 3) 改进版二【堆排序】
    • 4) 改进版三【分区海选】
  • 4. 最优算法

本文为Python算法题集之一的代码示例

题23:合并K个升序链表

1. 示例说明

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

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

    示例 1:

    输入: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
    

    示例 2:

    输入:lists = []
    输出:[]
    

    示例 3:

    输入:lists = [[]]
    输出:[]
    

    提示:

    • k == lists.length
    • 0 <= k <= 10^4
    • 0 <= lists[i].length <= 500
    • -10^4 <= lists[i][j] <= 10^4
    • lists[i]升序 排列
    • lists[i].length 的总和不超过 10^4

2. 题目解析

- 题意分解

  1. 本题为对多个排序链表进行合并
  2. 基本的解法是双层循环,外循环次数为所有元素个数,内循环为K次比较

- 优化思路

  1. 通常优化:减少循环层次

  2. 通常优化:增加分支,减少计算集

  3. 通常优化:采用内置算法来提升计算速度

  4. 分析题目特点,分析最优解

    1. 可以考虑采用堆结构来进行排序

    2. 可以采用分治法对多链表进行两两合并,化整为零,递归处理

    3. 可以用列表排序法进行简单排序


- 测量工具

  • 本地化测试说明:LeetCode网站测试运行时数据波动很大,因此需要本地化测试解决这个问题
  • CheckFuncPerf(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块
  • 本题本地化超时测试用例自己生成,详见【最优算法章节】

3. 代码展开

1) 标准求解【双层循环】

外层循环,内层最小值检测,依次将最小节点连接起来,性能自然不是最求目标

勉强通关,超过07%在这里插入图片描述

import CheckFuncPerf as cfp

class Solution:
 @staticmethod
 def mergeKLists_base(lists):
     ilen = len(lists)
     if ilen < 1:
         return None
     res_head = ListNode(0)
     tmpNode = res_head
     blast = True
     while blast:
         blast, bNone = False, True
         for iIdx in range(ilen):
             if lists[iIdx]:
                 if bNone:
                     minVal, minidx, bNone = lists[iIdx].val, iIdx, False
                 else:
                     if lists[iIdx].val < minVal:
                         minVal, minidx, bNone = lists[iIdx].val, iIdx, False
         if not bNone:
             blast = True
             tmpNode.next = lists[minidx]
             lists[minidx] = lists[minidx].next
             tmpNode = tmpNode.next
     return res_head.next

result = cfp.getTimeMemoryStr(Solution.mergeKLists_base, alists)
print(result['msg'], '执行结果 = {}'.format(result['result'].val))

# 运行结果
函数 mergeKLists_base 的运行时间为 950.22 ms;内存使用量为 4.00 KB 执行结果 = 0

2) 改进版一【列表排序】

将所有节点均存入列表结构,通过列表排序,最后再连接起来,代码简洁,性能优异,但是内存O(n)

性能卓越,超越96%在这里插入图片描述

import CheckFuncPerf as cfp

class Solution:
 @staticmethod
 def mergeKLists_ext1(lists):
     ilen = len(lists)
     if ilen < 1:
         return None
     list_node = []
     for iIdx in range(ilen):
         while lists[iIdx]:
             list_node.append([lists[iIdx].val, lists[iIdx]])
             lists[iIdx] = lists[iIdx].next
     sort_list = sorted(list_node, key=lambda x: x[0])
     for iIdx in range(len(sort_list)-1):
         sort_list[iIdx][1].next = sort_list[iIdx+1][1]
     sort_list[-1][1].next = None
     return sort_list[0][1]

result = cfp.getTimeMemoryStr(Solution.mergeKLists_ext1, alists)
print(result['msg'], '执行结果 = {}'.format(result['result'].val))

# 运行结果
函数 mergeKLists_ext1 的运行时间为 913.20 ms;内存使用量为 992.00 KB 执行结果 = 0

3) 改进版二【堆排序】

应用堆队列heapq来进行最小值检测,代码相对简洁,性能还行

马马虎虎,超过72%在这里插入图片描述

import CheckFuncPerf as cfp

class Solution:
 @staticmethod
 def mergeKLists_ext2(lists):
     import heapq
     res_head = ListNode(0)
     tmpNode = res_head
     buffmin = []
     for iIdx in range(len(lists)):
         if lists[iIdx] :
             heapq.heappush(buffmin, (lists[iIdx].val, iIdx))
             lists[iIdx] = lists[iIdx].next
     while buffmin:
         minval, minidx = heapq.heappop(buffmin)
         tmpNode.next = ListNode(minval)
         tmpNode = tmpNode.next
         if lists[minidx]:
             heapq.heappush(buffmin, (lists[minidx].val, minidx))
             lists[minidx] = lists[minidx].next
     return res_head.next

result = cfp.getTimeMemoryStr(Solution.mergeKLists_ext1, alists)
print(result['msg'], '执行结果 = {}'.format(result['result'].val))

# 运行结果
函数 mergeKLists_ext2 的运行时间为 958.21 ms;内存使用量为 4.00 KB 执行结果 = 0

4) 改进版三【分区海选】

使用递归设计,每次合并两个链表,直到最后合成总链表;这种方式类似分区海选,不是每个选手都要面对所有人,效率最高,资源最少

性能卓越,超越95%在这里插入图片描述

import CheckFuncPerf as cfp

class Solution:
 @staticmethod
 def mergeKLists_ext3(lists):
     def mergeTwoLists(link1, link2) -> ListNode:
         res_head = ListNode(0)  
         tmpNode = res_head  
         while link1 and link2: 
             if link1.val < link2.val:
                 tmpNode.next = link1  
                 link1 = link1.next
             else:
                 tmpNode.next = link2
                 link2 = link2.next
             tmpNode = tmpNode.next
         tmpNode.next = link1 if link1 else link2 
         return res_head.next 
     def mergeSort(lists, left, right) -> ListNode:
         if left == right:
             return lists[left]
         mid = (left + right) // 2
         leftlink = mergeSort(lists, left, mid)  
         rightlink = mergeSort(lists, mid + 1, right)
         return mergeTwoLists(leftlink, rightlink) 
     ilen = len(lists)
     if ilen < 1:
         return None
     return mergeSort(lists, 0, ilen - 1)

result = cfp.getTimeMemoryStr(Solution.mergeKLists_ext3, alists)
print(result['msg'], '执行结果 = {}'.format(result['result'].val))

# 运行结果
函数 mergeKLists_ext3 的运行时间为 393.49 ms;内存使用量为 0.00 KB 执行结果 = 0

4. 最优算法

根据本地日志分析,最优算法为第4种mergeKLists_ext3

def generateOneLinkedList(data):
    head = ListNode()
    current_node = head
    for num in data:
        new_node = ListNode(num)
        current_node.next = new_node
        current_node = new_node
    return head.next
def generateOneLinks(listlink):
    result = []
    for iIdx in range(len(listlink)):
        result.append(generateOneLinkedList(listlink[iIdx]))
    return result
iLen, k = 100000, 10
listnums = []
for iIdx in range(k):
    tmpNums = [x*(iIdx+1) for x in range(iLen)]
    listnums.append(tmpNums)
alists = generateOneLinks(listnums)
result = cfp.getTimeMemoryStr(Solution.mergeKLists_base, alists)
print(result['msg'], '执行结果 = {}'.format(result['result'].val))

# 算法本地速度实测比较
函数 mergeKLists_base 的运行时间为 950.22 ms;内存使用量为 4.00 KB 执行结果 = 0
函数 mergeKLists_ext1 的运行时间为 913.20 ms;内存使用量为 992.00 KB 执行结果 = 0
函数 mergeKLists_ext2 的运行时间为 958.21 ms;内存使用量为 4.00 KB 执行结果 = 0
函数 mergeKLists_ext3 的运行时间为 393.49 ms;内存使用量为 0.00 KB 执行结果 = 0

一日练,一日功,一日不练十日空

may the odds be ever in your favor ~

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

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

相关文章

论文介绍 FreeControl: 无需额外训练实现文本到图像的空间操控!

论文介绍 FreeControl: 无需额外训练实现文本到图像的空间操控&#xff01; 论文介绍 FreeControl: Training-Free Spatial Control of Any Text-to-Image Diffusion Model with Any Condition 关注微信公众号: DeepGo 项目地址&#xff1a;https://genforce.github.io/freeco…

【Java程序设计】【C00266】基于Springboot的超市进存销管理系统(有论文)

【Java程序设计】【C00266】基于Springboot的超市进存销管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的超市进销存系统 本系统分为登录注册模块、管理员功能模块以及员工功能模块。 登录注册模块&#…

Java学习18-- Override方法重写【★】

重点&#xff1a;super类 & 方法重写 ★看不明白多看几遍&#xff0c;记住static优先级>>高于override 重写Override methods★ 重写Override&#xff1a;child class可以覆盖father class中的method&#xff0c;即子类child class和父类father class有相同名称、…

如何部署一个高可用的 Linux 集群?

部署一个高可用的 Linux 集群需要经过多个步骤和考虑因素。以下是一个简要的指南&#xff0c;帮助您了解如何部署一个高可用的 Linux 集群&#xff1a; 确定需求和目标&#xff1a;在开始部署之前&#xff0c;您需要明确高可用性的定义和目标。对于一些组织而言&#xff0c;高…

鸿蒙开发第3篇__大数据量的列表加载性能优化

列表 是最常用到的组件 一 ForEach 渲染控制语法————Foreach Foreach的作用 遍历数组项&#xff0c;并创建相同的布局组件块在组件加载时&#xff0c; 将数组内容数据全部创建对应的组件内容&#xff0c; 渲染到页面上 const swiperImage: Resource[] {$r("app.me…

2024春晚纸牌魔术原理----环形链表的约瑟夫问题

一.题目及剖析 https://www.nowcoder.com/practice/41c399fdb6004b31a6cbb047c641ed8a?tabnote 这道题涉及到数学原理,有一般公式,但我们先不用公式,看看如何用链表模拟出这一过程 二.思路引入 思路很简单,就试创建一个单向循环链表,然后模拟报数,删去对应的节点 三.代码引…

数据库管理-第150期 Oracle Vector DB AI-02(20240212)

数据库管理150期 2024-02-12 数据库管理-第150期 Oracle Vector DB & AI-02&#xff08;20240212&#xff09;1 LLM2 LLM面临的挑战3 RAG4 向量数据库LLM总结 数据库管理-第150期 Oracle Vector DB & AI-02&#xff08;20240212&#xff09; 作者&#xff1a;胖头鱼的鱼…

LeetCode:69.x的平方根

嗨嗨嗨&#xff0c;二分又来了&#xff0c;淦它&#xff0c; 这个题官解是&#xff0c;C函数法&#xff0c;二分&#xff0c;和牛顿迭代法&#xff08;暂且搁置&#xff09;&#xff0c; 当然还有暴力&#xff08;不必讨论&#xff0c;就从0开始一个一个试&#xff09;&#…

2.11日学习打卡----初学RocketMQ(二)

2.11日学习打卡 一. RocketMQ整合springboot 首先配置pom.xml文件 <dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>annotationProcessor</scope></dependency><dependency>…

服装效果图为何要用云渲染100?渲染100邀请码1a12

服装行业是充满创意和竞争的领域&#xff0c;而服装效果图是其中重要一环&#xff0c;以前效果图都是本地渲染&#xff0c;现在越来越多的设计师转向云渲染&#xff0c;以国内最专业的平台渲染100为例&#xff0c;云渲染有以下好处&#xff1a; 1、提高工作效率 设计师可以利用…

Netty源码系列 之 FastThreadLocal源码

目录 Netty优化方案之 FastThreadLocal 前言 ThreadLocal ThreadLocal是干什么的&#xff1f; 为什么要使用ThreadLocal工具类去操控存取目标数据到Thread线程 &#xff1f; ThreadLocal的使用场景 目标数据存储到Thread线程对象的哪里&#xff1f; 怎么样把一个目标数据…

JavaWeb:SpingBoot原理 --黑马笔记

1. 配置优先级 在我们前面的课程当中&#xff0c;我们已经讲解了SpringBoot项目当中支持的三类配置文件&#xff1a; application.properties application.yml application.yaml 在SpringBoot项目当中&#xff0c;我们要想配置一个属性&#xff0c;可以通过这三种方式当中…

Ubuntu Desktop - Terminal 输出全部选中 + 复制

Ubuntu Desktop - Terminal 输出全部选中 复制 1. Terminal2. Terminal 最大化3. Edit -> Select All4. Copy & PasteReferences 1. Terminal 2. Terminal 最大化 3. Edit -> Select All 4. Copy & Paste Edit -> Copy or Shift Ctrl C Edit -> Paste…

【Python网络编程之TCP三次握手】

&#x1f680; 作者 &#xff1a;“码上有前” &#x1f680; 文章简介 &#xff1a;Python开发技术 &#x1f680; 欢迎小伙伴们 点赞&#x1f44d;、收藏⭐、留言&#x1f4ac; Python网络编程之[TCP三次握手] 代码见资源&#xff0c;效果图如下一、实验要求二、协议原理2.…

Microsoft Excel 加载数据分析工具

Microsoft Excel 加载数据分析工具 1. 打开 Excel&#xff0c;文件 -> 选项2. 加载项 -> 转到…3. 分析工具库、分析工具库 - VBA4. 打开 Excel&#xff0c;数据 -> 数据分析References 1. 打开 Excel&#xff0c;文件 -> 选项 2. 加载项 -> 转到… ​​​ 3…

Win32 控制台绘图2

之前已经了解在控制台可以调用Win32 api绘图&#xff1b;下面继续加深一下此概念&#xff1b; #include <stdio.h> #include <stdlib.h> #include <windows.h>HWND WINAPI GetConsoleWindow();int main(int argc, char *argv[]) {HWND hwnd; HDC hdc; HPE…

【MySQL探索之旅】MySQL数据库下载及安装教程

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有…

c++ 内存

c 内存 内存分区 1.代码区&#xff1a;程序的机器指令&#xff0c;可以被机器直接执行。 属性&#xff1a;只读和共享 代码区包含什么&#xff1a; 在程序编译时就已经被分配好了地址&#xff0c;并保存在可执行文件的代码段中。当程序运行时&#xff0c;操作系统会将代码段的…

【C++】类的隐式类型转换

文章目录 前言一、隐式类型转换二、explicit关键字总结 前言 一、隐式类型转换 C 类的隐式类型转换是指当一个类定义了适当的构造函数或转换函数时&#xff0c;可以在需要时自动进行类型转换&#xff0c;而无需显式调用转换函数或构造函数。这使得代码更具灵活性和简洁性。下面…

一种简单的车辆过减速带识别方法

识别方法参考以下图片上的这篇论文第三章&#xff0c;有需要的自行知网下载。 一、离散冲击路面建立 我们之前已经搭建了C级路面&#xff0c;直接在C级路面中间某一段加上减速带就可以。这里我加的减速带&#xff0c;如下图所示&#xff0c;高30mm&#xff0c;凸台宽约20mm&am…