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 cfpclass Solution:@staticmethoddef mergeKLists_base(lists):ilen = len(lists)if ilen < 1:return Noneres_head = ListNode(0)tmpNode = res_headblast = Truewhile blast:blast, bNone = False, Truefor iIdx in range(ilen):if lists[iIdx]:if bNone:minVal, minidx, bNone = lists[iIdx].val, iIdx, Falseelse:if lists[iIdx].val < minVal:minVal, minidx, bNone = lists[iIdx].val, iIdx, Falseif not bNone:blast = TruetmpNode.next = lists[minidx]lists[minidx] = lists[minidx].nexttmpNode = tmpNode.nextreturn res_head.nextresult = 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 cfpclass Solution:@staticmethoddef mergeKLists_ext1(lists):ilen = len(lists)if ilen < 1:return Nonelist_node = []for iIdx in range(ilen):while lists[iIdx]:list_node.append([lists[iIdx].val, lists[iIdx]])lists[iIdx] = lists[iIdx].nextsort_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 = Nonereturn 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 cfpclass Solution:@staticmethoddef mergeKLists_ext2(lists):import heapqres_head = ListNode(0)tmpNode = res_headbuffmin = []for iIdx in range(len(lists)):if lists[iIdx] :heapq.heappush(buffmin, (lists[iIdx].val, iIdx))lists[iIdx] = lists[iIdx].nextwhile buffmin:minval, minidx = heapq.heappop(buffmin)tmpNode.next = ListNode(minval)tmpNode = tmpNode.nextif lists[minidx]:heapq.heappush(buffmin, (lists[minidx].val, minidx))lists[minidx] = lists[minidx].nextreturn res_head.nextresult = 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 cfpclass Solution:@staticmethoddef 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.nextelse:tmpNode.next = link2link2 = link2.nexttmpNode = tmpNode.nexttmpNode.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) // 2leftlink = mergeSort(lists, left, mid)  rightlink = mergeSort(lists, mid + 1, right)return mergeTwoLists(leftlink, rightlink) ilen = len(lists)if ilen < 1:return Nonereturn 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 = headfor num in data:new_node = ListNode(num)current_node.next = new_nodecurrent_node = new_nodereturn 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 ~

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

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

相关文章

LeetCode Python - 13.罗马数字转整数

目录 题目答案运行结果 题目 罗马数字包含以下七种字符: I&#xff0c; V&#xff0c; X&#xff0c; L&#xff0c;C&#xff0c;D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如&#xff0c; 罗马数字 2 写做 II &#xff0c;即为两个并列的 1 。12 写做 XII…

three.js 细一万倍教程 从入门到精通(二)

目录 三、全面认识three.js物体 3.1、掌握几何体顶点_UV_法向属性 3.2、BufferGeometry设置顶点创建矩形 3.3、生成酷炫三角形科技物体 四、详解材质与纹理 4.1、初识材质与纹理 4.2、详解纹理偏移_旋转_重复 偏移 旋转 重复 4.3、设置纹理显示算法与mipmap mapFil…

Stable Diffusion 模型下载:Disney Pixar Cartoon Type B(迪士尼皮克斯动画片B类)

本文收录于《AI绘画从入门到精通》专栏,专栏总目录:点这里。 文章目录 模型介绍生成案例案例一案例二案例三案例四案例五案例六案例七案例八案例九案例十

vue-组件组成和组件通信(四)

组件的三大组成部分 (结构/样式/逻辑) scoped样式冲突 默认情况&#xff1a;写在组件中的样式会 全局生效 → 因此很容易造成多个组件之间的样式冲突问题。 1. 全局样式: 默认组件中的样式会作用到全局 2. 局部样式: 可以给组件加上 scoped 属性, 可以让样式只作用于当前组…

Linux系统调试课:Linux错误码介绍

文章目录 一、错误码二、错误码返回案例三、使用 goto 语句沉淀、分享、成长,让自己和他人都能有所收获!😄 📢错误代码由内核或用户空间应用程序(通过errno变量)解释。错误处理在软件开发中非常重要,而不仅仅是在内核开发中。幸运的是,内核提供的几种错误,几乎涵盖了可…

Verilog刷题笔记30

题目&#xff1a; You are provided with a BCD one-digit adder named bcd_fadd that adds two BCD digits and carry-in, and produces a sum and carry-out. 解题&#xff1a; module top_module( input [399:0] a, b,input cin,output cout,output [399:0] sum );reg [99…

opencv 图像色彩空间转化

今天看了b站贾志刚的课&#xff0c;觉得不错&#xff0c;特地做学习笔记来和小伙伴分享 贾志刚的这个好像是2.0版本,30小时的,语言更加精炼,适合初级入门学习 第一节是常规安装 看他的步骤装就行了,记得配置完点应用再点确定,我第一次就是 没点然后就失败了,又得重配置一次…

Elasticsearch 通信模块的分析

Elasticsearch 通信模块的分析 - 知乎 Elasticsearch是一个基于Lucene的分布式实时搜索框架&#xff0c;它本身能够接受用户发来的http 请求&#xff0c; 集群节点之间也会有相关的通信。 通信模块的简介 Elasticsearch 中的通信相关的配置都是由NetworkModule 这个类完成的…

文心一言“拜师”了!金灿荣、王先进等成为首批“文心导师”

12月28日&#xff0c;由深度学习技术及应用国家工程研究中心主办的WAVE SUMMIT深度学习开发者大会2023在北京召开。百度首席技术官、深度学习技术及应用国家工程研究中心主任王海峰现场公布了飞桨文心五载十届最新生态成果&#xff0c;文心一言最新用户规模破1亿&#xff0c;截…

TCP和UDP相关问题(重点)——7.TCP的流量控制怎么实现的?

流量控制就是在双方通信时&#xff0c;发送方的速率和接收方的速率不一定是相等的&#xff0c;如果发送方发送的太快&#xff0c;接收方就只能把数据先放到接收缓冲区中&#xff0c;如果缓冲区都满了&#xff0c;那么处理不过来就只能丢弃&#xff0c;所以需要控制发送方的速率…

34 使用 LNMP 架构部署动态网站环境

源码包程序 LNMP 动态网站部署架构 LNMP 动态网站部署架构是一套由 Linux Nginx MySQL PHP 组成的动态网站系统 解决方案。 1. 准备工作 在使用源码包安装服务程序之前&#xff0c;首先要让安装主机具备编译程序源码的环境。这需要 具备 C 语言、C语言、Perl 语言的编译器&…

java之filter过滤器

1、概念 2、过程 3. 实现 4. 参考链接 参考的b站链接