Leetcode 剑指 Offer II 077.排序链表

题目难度: 中等

原题链接

今天继续更新 Leetcode 的剑指 Offer(专项突击版)系列, 大家在公众号 算法精选 里回复 剑指offer2 就能看到该系列当前连载的所有文章了, 记得关注哦~

题目描述

给定链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

示例 1:

  • 输入:head = [4,2,1,3]
  • 输出:[1,2,3,4]

示例 2:

  • 输入:head = [-1,5,3,4,0]
  • 输出:[-1,0,3,4,5]

示例 3:

  • 输入:head = []
  • 输出:[]

提示:

  • 链表中节点的数目在范围 [0, 5 * 10^4] 内
  • -10^5 <= Node.val <= 10^5

进阶:你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?

题目思考

  1. 如何做到 O(n log n) 时间复杂度和常数级空间复杂度?

解决方案

思路
  • 分析题目, 一个很容易想到的思路就是将链表每个节点存到一个数组中, 然后使用自定义排序, 对数组按照节点的值从小到大排序, 再依次连起来即可
  • 不过这样虽说时间复杂度可以做到 O(NlogN), 但使用了额外空间, 不满足进阶要求, 如何优化呢?
  • 要想做到常数级空间复杂度排序, 首先就不能采用递归, 因为递归有额外递归栈的空间消耗
  • 另外题目给的是单向链表, 不好从后往前遍历, 所以经典的快速排序在这里也不适用, 如果额外增加向前的连接, 又需要额外空间
  • 常见的 O(NlogN)排序还有归并排序, 虽然递归归并的实现方式比较经典, 但我们也可以利用迭代的方式实现, 这样就可以做到常数级空间复杂度
  • 具体思路就是先将相邻的单个节点进行归并, 然后再将 2 个节点作为整体, 将相邻部分归并, 然后是 4 个, 8 个, 以此类推, 最终实现全部节点的排序
  • 举个例子, 对于链表1->5->4->3->0->2
    1. 第一步, 对相邻节点从小到大归并排序, 即 1 和 5 归并, 4 和 3 归并, 0 和 2 归并, 得到1->5->3->4->0->2
    2. 第二步, 对相邻两个节点从小到大归并排序, 即1->53->4归并, 0->2不变, 得到1->3->4->5->0->2
    3. 第二步, 对相邻四个节点从小到大归并排序, 即1->3->4->50->2归并, 得到0->1->2->3->4->5
  • 这样只需要 logN 次归并, 然后每次归并只需要遍历每个节点常数次, 总体时间复杂度是 O(NlogN), 且没有使用额外空间
  • 具体实现方面, 我们需要记录链表总长度和当前归并部分的长度
  • 然后针对每个归并长度遍历整个链表, 分别得到当前待归并的左右部分, 归并后再继续下个左右部分的归并, 直到达到末尾
  • 最终当归并长度大于等于总长度时, 说明整个链表已经排序好了, 返回链表头即可
  • 另外注意在遍历过程中需要处理好节点的连接关系, 避免导致无限循环
  • 下面代码给出了每一步详细的注释, 大家可以结合代码和注释来理解
复杂度
  • 时间复杂度 O(NlogN): 每次归并排序的长度都是上次长度乘以 2, 所以一共只需要归并 logN 次, 然后每次归并时需要遍历所有节点两遍 (一遍记录左右部分的头和尾, 一遍实际归并), 这部分时间复杂度是 O(N), 所以整体时间复杂度就是 O(NlogN)
  • 空间复杂度 O(1): 只使用了几个常数空间的变量
代码
class Solution:def sortList(self, head: ListNode) -> ListNode:def merge(head1, head2):# 将链表head1和head2进行归并排序# 使用哨兵节点简化处理dummy = ListNode(0)cur = dummywhile head1 or head2:if not head2 or head1 and head1.val <= head2.val:# head2为空, 或者head1的值更小, 追加head1cur.next = head1# head1向后移动head1 = head1.nextelse:# 此时只能追加head2cur.next = head2# head2向后移动head2 = head2.next# 当前节点向后移动cur = cur.next# 返回归并排序后的链表头和尾return (dummy.next, cur)# 统计原始链表的节点数n = 0cur = headwhile cur:cur = cur.nextn += 1# 从长度为1的两个链表开始归并排序cnt = 1# 使用哨兵节点简化处理dummy = ListNode(0, head)# 只要长度不超过n, 就说明有至少两个链表需要归并while cnt < n:# ptail存储前一个归并好的链表的末尾, 初始化为哨兵ptail = dummy# cur是当前处理的节点cur = dummy.nextwhile cur:# lhead和ltail是当前待归并的左侧链表头和尾lhead = curltail = cur# 遍历lcnt个节点, 并更新ltail和curlcnt = cntwhile lcnt > 0 and cur:ltail = curcur = cur.nextlcnt -= 1if ltail:# 断开ltail和右侧的连接ltail.next = None# rhead和rtail是当前待归并的右侧链表头和尾rhead = currtail = cur# 遍历rcnt个节点, 并更新rtail和currcnt = cntwhile rcnt > 0 and cur:rtail = curcur = cur.nextrcnt -= 1if rtail:# 断开rtail和右侧的连接rtail.next = None# 归并左右链表, 得到归并后的新链表的头和尾nhead, ntail = merge(lhead, rhead)# 将前一个归并部分的尾指向当前归并部分的头ptail.next = nhead# 然后更新ptail尾当前归并部分的尾ptail = ntail# 归并长度乘以2, 不断循环归并排序更大长度的两部分, 直到整个链表有序cnt *= 2# 最终哨兵节点的下一个节点就是全部排序后的头return dummy.next

大家可以在下面这些地方找到我~😊

我的 GitHub

我的 Leetcode

我的 CSDN

我的知乎专栏

我的头条号

我的牛客网博客

我的公众号: 算法精选, 欢迎大家扫码关注~😊

算法精选 - 微信扫一扫关注我

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

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

相关文章

Xilinx 千兆以太网TEMAC IP核 MDIO 配置及物理接口

基于AXI4-Lite接口可以访问MDIO(Management Data Input/Output)接口&#xff0c;而MDIO接口连接MAC外部的PHY芯片&#xff0c;用户可通过AXI4-Lite接口实现对PHY芯片的配置。 1 MDIO接口简介 开放系统互连模型OSI的最低两层分别是数据链路层和物理层&#xff0c;数据链路层的…

音视频入门基础:像素格式专题(2)——不通过第三方库将RGB24格式视频转换为BMP格式图片

音视频入门基础&#xff1a;像素格式专题系列文章&#xff1a; 音视频入门基础&#xff1a;像素格式专题&#xff08;1&#xff09;——RGB简介 音视频入门基础&#xff1a;像素格式专题&#xff08;2&#xff09;——不通过第三方库将RGB24格式视频转换为BMP格式图片 一、引…

xilinx xdma drive 传输8MB以上数据受限的问题

当传输超过8 MB数据时报错error code1359&#xff0c; #define XDMA_MAX_TRANSFER_SIZE (8UL * 1024UL * 1024UL) 可以修改成&#xff1a; #define XDMA_MAX_TRANSFER_SIZE (80UL * 1024UL * 1024UL) VS2019 WDK环境的搭建 先准备好VS WDK的驱动开发环境。需要下载VS、SD…

5 个遥遥领先的大模型 RAG 工具

想象一下拥有一种超能力&#xff0c;让你能够对任何问题或提示生成类似人类的回答&#xff0c;同时还能够利用庞大的外部知识库确保准确性和相关性。这不是科幻小说&#xff0c;这就是检索增强生成&#xff08;RAG&#xff09;的力量。 在本文中&#xff0c;我们将介绍五大遥遥…

NASA数据集——2002-2011年全球18.7 至 89.0 千兆赫的亮度温度、海冰浓度和海冰积雪深度三级网格产品(AE_SI12)数据

AMSR-E/Aqua Daily L3 12.5 km Brightness Temperature, Sea Ice Concentration, & Snow Depth Polar Grids V003 三级网格产品&#xff08;AE_SI12&#xff09;包括 18.7 至 89.0 千兆赫的亮度温度、海冰浓度和海冰积雪深度。 简介 美国国家航空航天局地球观测系统 Aqu…

几个Python处理Excel实际应用

下面介绍四个不同类型的Python处理Excel的经典应用案例&#xff0c;以帮助读者更好地掌握Python处理Excel的技能。 一、读取Excel数据 Python通过pandas库可以轻松地读取Excel数据。pandas库是一个专门用于数据分析和处理的库&#xff0c;它可以将Excel中的数据读取为DataFra…

HIVE调优MapJoin

HIVE调优MapJoin 目录 HIVE调优MapJoin 1.mapjoin &#xff08;1.2以后自动默认启动mapjoin&#xff09; 2.创建表格 3.查询建表 4.通过 explain 展示执行计划 5.Map JOIN 相关设置&#xff1a; 1.mapjoin &#xff08;1.2以后自动默认启动mapjoin&#xff09;…

08.3.grafana自定义图形

grafana自定义图形 找插件里面的zabbix 点击update 数据源—zabbix数据源,添加zabbix数据源 选择zabbix类型 我这里配置的是本地&#xff0c;所以URL直接localhost 这里配置zabbix登录账号密码Admin/zabbix 然后点击保存并测试&#xff0c;会直接显示版本 导入模板&…

2024年数维杯数学建模

高质量原创论文已完成 需要的私我

【软考高项】四十四、高级项目管理

一、项目集管理 相关角色 项目集发起人、项目集指导委员会、项目集经理、其他影响项目集的干系人项目集管理绩效域 项目集战略一致性、项目集效益管理、项目集干系人参与、项目集治理和项目集生命周期管理 二、项目组合管理 项目组合经理角色 项目组合管理原…

【深度学习】Diffusion扩散模型的逆扩散问题

1、前言 上一篇&#xff0c;我们讲了Diffusion这个模型的原理推导。但在推导中&#xff0c;仍然遗留了一些问题。本文将解决那些问题 参考论文&#xff1a; ①Variational Diffusion Models (arxiv.org) ②Tutorial on Diffusion Models for Imaging and Vision (arxiv.org…

Mysql数据库的基础学习

为什么使用数据库&#xff1f; 1.持久化&#xff1a;将数据保存到可掉电式存储设备中以供使用。 数据库相关概念&#xff1a; DB:数据库&#xff08;Databass&#xff09;即存储数据的仓库&#xff0c;本质是一个文件系统&#xff0c;保存了一系列有组织的数据DBMS:数据库管…