148.排序链表

文章目录

  • 方法1:自顶向下的归并排序
  • 方法2 自底向上的归并排序

方法1:自顶向下的归并排序

使用归并排序算法。归并排序是一种分治算法,它将链表分成两半,然后对每一半进行排序,最后将两个有序的链表合并。由于链表不支持随机访问,我们不能像数组那样直接分割,但可以通过快慢指针找到中点,然后进行分割。

自而向下的归并排序

  1. 先找到链表的中间,然后将其分为左右两部分
  2. 分别对左右两部分进行递归,归并排序
  3. 将这两部分用merge函数合并起来

这个题目考察的知识点比较全面,用到的merge函数,其实就是对两个有序链表进行合并的题目21. 合并两个有序链表

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:# 方法1. 从下往上的归并排序# 1. 先找到链表的中间midif not head or not head.next:return head slow = head fast = head.next while fast and fast.next:fast = fast.next.next slow = slow.next # if fast: # 偶数   #     slow = slow.next # 分割链表 !!!!!!mid = slow.next slow.next = Noneleft = self.sortList(head)right = self.sortList(mid)return self.mergeList(left, right)def mergeList(self, left: Optional[ListNode], right: Optional[ListNode]) -> Optional[ListNode]:# 方法1:递归方法,空间复杂度为O(n)   时间复杂度为O(nlogn)if left == None:return right elif right == None:return left elif left.val < right.val:left.next = self.mergeList(left.next, right)return leftelse:right.next = self.mergeList(left, right.next)return right # 方法2:迭代方法,空间复杂度为O(1)   时间复杂度O(nlog n)# if left == None:#     return right # elif right == None:#     return left # dummy = ListNode(0)# current = dummy # while left and right:#     if left.val < right.val:#         current.next = left#         left = left.next #     else:#         current.next = right #         right = right.next #     current = current.next # if left:#     current.next = left # else:#     current.next = right # return dummy.next
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:if not head or not head.next:return head# 找到链表的中点slow, fast = head, head.nextwhile fast and fast.next:slow = slow.nextfast = fast.next.next# 分割链表mid = slow.nextslow.next = None# 递归排序两半链表left = self.sortList(head)right = self.sortList(mid)# 合并两个有序链表return self.merge(left, right)def merge(self, left: ListNode, right: ListNode) -> ListNode:# 合并两个有序列表left, right dummy = ListNode(0)tail = dummywhile left and right:if left.val < right.val:tail.next = leftleft = left.nextelse:tail.next = rightright = right.nexttail = tail.next# 连接剩余部分tail.next = left or rightreturn dummy.next

方法2 自底向上的归并排序

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:def sortList(self, head: ListNode) -> ListNode:# merge函数,将有序的head1,head2合并为一个有序的链表def merge(head1: ListNode, head2: ListNode) -> ListNode:dummyHead = ListNode(0)temp, temp1, temp2 = dummyHead, head1, head2while temp1 and temp2:if temp1.val <= temp2.val:temp.next = temp1temp1 = temp1.nextelse:temp.next = temp2temp2 = temp2.nexttemp = temp.nextif temp1:temp.next = temp1elif temp2:temp.next = temp2return dummyHead.next# sortList 函数首先计算链表的长度,然后使用一个哑节点 dummyHead 来简化头节点操作。# subLength 表示当前需要排序的子链表的长度,初始值为1,每次循环翻倍。# 在每次循环中,我们遍历链表,将链表分割成若干长度为 subLength 的子链表,然后使用 merge 函数将它们两两合并。# 这段代码通过自底向上的方式实现了链表的归并排序,空间复杂度为 O(1)。# 如果链表为空,if not head:return head# 计算链表的长度length = 0node = headwhile node:length += 1node = node.nextdummyHead = ListNode(0, head)subLength = 1while subLength < length:prev, curr = dummyHead, dummyHead.nextwhile curr:# 把链表分割成若干长度为 subLength 的子链表# 第一个子链表的头为head1head1 = currfor i in range(1, subLength):if curr.next:curr = curr.nextelse:break# 第二个子链表的头为head2head2 = curr.nextcurr.next = None # 将第一个子链表进行收尾curr = head2for i in range(1, subLength):if curr and curr.next:curr = curr.nextelse:breaksucc = None           # succ为余下的链表的开头if curr:succ = curr.nextcurr.next = None   # 将第二个子链表进行收尾# 将合并好的结果放入到dummy后面去merged = merge(head1, head2)prev.next = mergedwhile prev.next:prev = prev.nextcurr = succsubLength <<= 1return dummyHead.next

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

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

相关文章

[Go语言快速上手]初识Go语言

目录 一、什么是Go语言 二、第一段Go程序 1、Go语言结构 注意 2、Go基础语法 关键字 运算符优先级 三、Go语言数据类型 示例 小结 一、什么是Go语言 Go语言&#xff0c;通常被称为Golang&#xff0c;是一种静态类型、编译型的计算机编程语言。它由Google的Robert Gr…

用HTML5+CSS+JavaScript庆祝国庆

用HTML5CSSJavaScript庆祝国庆 中华人民共和国的国庆日是每年的10月1日。 1949年10月1日&#xff0c;中华人民共和国中央人民政府成立&#xff0c;在首都北京天安门广场举行了开国大典&#xff0c;中央人民政府主席毛泽东庄严宣告中华人民共和国成立&#xff0c;并亲手升起了…

Vue3 中Ref的最佳实践

在vue3中如果我们需要获取一个响应式的变量&#xff0c;可以使用ref来定义一个变量。 const name ref( "" );name.value "test" 定义好后&#xff0c;就可以实现修改状态&#xff0c;更新UI的效果了。 在这个基础上&#xff0c;本文主要讨论跨组件时如何…

Discord:报错:A fatal Javascript error occured(解决办法)

按 Windows 键 R 并输入 %appdata% 选择 discord 文件夹并将其删除。 再次按 Windows 键 R 并输入 %LocalAppData% 选择 discord 文件夹并再次将其删除。 附加&#xff1a; 如果还不行&#xff0c;就通过官网下载吧&#xff0c;这个问题通过epic下载可能会有

Python并发编程挑战与解决方案

Python并发编程挑战与解决方案 并发编程是现代软件开发中的一项核心能力&#xff0c;它允许多个任务同时运行&#xff0c;提高程序的性能和响应速度。Python因其易用性和灵活性而广受欢迎&#xff0c;但其全局解释器锁&#xff08;GIL&#xff09;以及其他特性给并发编程带来了…

Docker面试-24年

1、Docker 是什么&#xff1f; Docker一个开源的应用容器引擎&#xff0c;是实现容器技术的一种工具&#xff0c;让开发者可以打包他们的应用以及环境到一个镜像中&#xff0c;可以快速的发布到任何流行的操作系统上。 2、Docker的三大核心是什么? 镜像&#xff1a;Docker的…

网络威胁情报技术的进步

网络威胁形势不断演变&#xff0c;必然导致防御者和攻击者之间持续展开军备竞赛。幸运的是&#xff0c;网络威胁情报 (CTI) 技术的进步为安全专业人员提供了强大的工具&#xff0c;使他们能够保持领先地位。 本指南深入探讨了 CTI 的最新进展&#xff0c;让您了解这些技术如何…

【学习笔记】手写一个简单的 Spring MVC

目录 一、什么是Spring MVC &#xff1f; Spring 和 Spring MVC 的区别&#xff1f; Spring MVC 的运行流程&#xff1f; 二、实现步骤 1. DispatcherServlet 1. 创建一个中央分发器 拦截所有请求 测试 2. 接管 IOC 容器 1. 创建配置文件 2. 修改 web.xml 配置文件 …

1分钟搞懂K8S中的NodeSelector

文章目录 NodeSelector是什么&#xff1f;为什么使用NodeSelector&#xff1f;怎么用NodeSelector&#xff1f;POD配置示例yaml配置示例 如何知道K8S上面有哪些节点&#xff0c;每个节点都有什么信息呢&#xff1f;1. 使用kubectl命令行工具查看所有节点及其标签2. 使用kubectl…

算法【Java】—— 二叉树的深搜

深搜 深搜简单来说就是一直递归到底&#xff0c;然后返回&#xff0c;以二叉树为例&#xff0c;就是从根节点出发一直搜索到叶子节点&#xff0c;然后想上返回。 这里简单说明一下&#xff1a;深搜的英文缩写是 dfs&#xff0c;下面定义深搜函数名我直接命名为 dfs 实战演练 …

内存占用估算方法

优质博文&#xff1a;IT-BLOG-CN 通过掌握每种数据类型的大小&#xff0c;就可以更准确地预测对象和数据的内存消耗。 一、基础数据类型 Java基础数据类型结构&#xff0c;在64位系统开启指针压缩情况下的内存占用字节数&#xff1a; booleanbytecharshortintlongfloatdoub…

PYTHON实现HTTP request的一些有用的函数

前言 我们知道&#xff0c;当需要设计一个程序和服务器进行交互时&#xff0c;往往会用到HTTP的request&#xff0c;即服务器有一个对外接口REST API&#xff0c;因此当向服务器发送符合格式要求的HTTP request时&#xff0c;服务器会给出响应&#xff0c;甚至执行一些任务。如…

码随想录算法训练营第62天|卡码网:97. 小明逛公园、127. 骑士的攻击

1. 卡码网 97. 小明逛公园 题目链接&#xff1a;https://kamacoder.com/problempage.php?pid1155 文章链接&#xff1a;https://www.programmercarl.com/kamacoder/0097.小明逛公园.html 思路&#xff1a; 使用Floyd 算法&#xff0c;目的是解决多源最短路问题&#xff0c;即 …

如何编写一个优雅的commit message

在Git中&#xff0c;git commit 命令扮演着至关重要的角色。它的主要作用是将暂存区&#xff08;staging area&#xff09;里的改动内容提交到本地仓库&#xff08;repository&#xff09;中&#xff0c;形成一个新的版本或提交&#xff08;commit&#xff09;。这个过程是 Git…

基于Node2Vec的图嵌入实现过程

目录 一、引言二、Node2Vec&#xff08;原理&#xff09;2.1 随机游走&#xff08;Random Walk&#xff09;2.2 嵌入学习2.3 Node2Vec 的优势 三、使用 Node2Vec 进行图嵌入&#xff08;实践&#xff09;3.1 读取和转换 JSON 文件为 Graph 对象3.2 训练 Node2Vec 模型3.3 二维嵌…

10款好用的开源 HarmonyOS 工具库

大家好&#xff0c;我是 V 哥&#xff0c;今天给大家分享10款好用的 HarmonyOS的工具库&#xff0c;在开发鸿蒙应用时可以用下&#xff0c;好用的工具可以简化代码&#xff0c;让你写出优雅的应用来。废话不多说&#xff0c;马上开整。 1. efTool efTool是一个功能丰富且易用…

Kotlin:2.0.20 的新特性

一、概述 Kotlin 2.0.20英文版官方文档 Kotlin 2.0.20发布了!这个版本包括对Kotlin 2.0.0的性能改进和bug修复&#xff0c;我们在其中宣布Kotlin K2编译器为Stable。以下是本次发布的一些亮点: 数据类复制函数将具有与构造函数相同的可见性来自默认目标层次结构的源集的静态访…

Python批量下载PPT模块并实现自动解压

日常工作中&#xff0c;我们总是找不到合适的PPT模板而烦恼。即使有免费的网站可以下载&#xff0c;但是一个一个地去下载&#xff0c;然后再批量解压进行查看也非常的麻烦&#xff0c;有没有更好方法呢&#xff1f; 今天&#xff0c;我们利用Python来爬取一个网站上的PPT&…

HTML+CSS基础用法介绍五

目录&#xff1a; 结构伪类选择器盒子模型-边框线盒子模型-内边距盒子模型-解决盒子被撑大盒子模型-外边距与版心居中小知识&#xff1a;清除浏览器中所有标签的默认样式内容溢出控制显示方式盒子模型-圆角 &#x1f40e;正片开始 结构伪类选择器 什么是结构伪类选择器&…

全新一区PID搜索算法+TCN-LSTM+注意力机制!PSA-TCN-LSTM-Attention多变量时间序列预测(Matlab)

全新一区PID搜索算法TCN-LSTM注意力机制&#xff01;PSA-TCN-LSTM-Attention多变量时间序列预测&#xff08;Matlab&#xff09; 目录 全新一区PID搜索算法TCN-LSTM注意力机制&#xff01;PSA-TCN-LSTM-Attention多变量时间序列预测&#xff08;Matlab&#xff09;效果一览基本…