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

【Day 20】148.排序链表

文章目录

  • 148.排序链表
  • 题目:
  • 思路:
  • 代码实现(Go):

148.排序链表

题目:

给你链表的头结点 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


思路:

  1. 递归终止条件

    • 如果链表为空或者只有一个节点,直接返回,因为空链表或单节点链表天然有序。
  2. 找到链表中点并切割

    • 使用快慢指针:

      • slow 每次走 1 步,fast 每次走 2 步。
      • fast 到达尾部时,slow 停在 左半段的尾节点
    • 将链表从中点切开:

      • 这样左半段从 head 开始,右半段从 second 开始,链表被分为两段。
  3. 递归排序左右两段

    • 递归地对左右半段进行排序,直到每段只剩 1 个节点或者为空

    • 递归调用逻辑

    • 对左半段 head -> ... -> slow 再次执行 sortList

      • 如果左半段长度 > 1,就会再次找中点、切割、递归
      • 最终递归到每段只有一个节点,就返回节点。
    • 对右半段 second -> ... 同理。

  • 结果

    • 左右两段分别返回排好序的链表头。
  1. 合并两个有序链表

    • 新建一个 dummy 节点作为合并链表的头部辅助节点。
    • 遍历左右两个链表,逐个比较节点值,把小的节点接到当前链表尾部。
    • 当一个链表耗尽,把另一个链表剩下的节点直接接上。
  2. 返回合并后的链表

    • dummy.Next 指向合并后的有序链表头。

在这里插入图片描述


  • 时间复杂度O(n log n)

    • 每次分半是 log n 层,合并两段是 O(n),总共 O(n log n)
  • 空间复杂度O(log n)

    • 递归栈的空间,因为链表不需要额外数组。
  • 适合链表的原因

    • 链表不适合快速排序那样的随机访问,但归并排序只需要顺序访问,非常自然。

代码实现(Go):

详细注解:

// package main// import "fmt"// type ListNode struct {
// 	Val  int
// 	Next *ListNode
// }func sortList(head *ListNode) *ListNode {if head == nil || head.Next == nil {return head // 空链表或单节点直接返回}// 1. 使用快慢指针找到链表中点slow, fast := head, head.Nextfor fast != nil && fast.Next != nil {slow = slow.Nextfast = fast.Next.Next}second := slow.Next // 右半段头保存起来使用,接下来要置空slow.Next = nil     // 切断链表,分成左右两段,左半段最后指向 nil// 2. 递归排序左右两段left := sortList(head)    // 第一段开头right := sortList(second) // 第二段开头// 3. 合并两个有序链表dummy := &ListNode{}cur := dummyfor left != nil && right != nil {if left.Val < right.Val {cur.Next = leftleft = left.Next} else {cur.Next = rightright = right.Next}cur = cur.Next}if left != nil {cur.Next = left} else {cur.Next = right}return dummy.Next
}// func main() {
// 	// 构造链表 [4,2,1,3]
// 	head := &ListNode{
// 		Val: 4,
// 		Next: &ListNode{
// 			Val: 2,
// 			Next: &ListNode{
// 				Val: 1,
// 				Next: &ListNode{
// 					Val:  3,
// 					Next: nil,
// 				},
// 			},
// 		},
// 	}// 	sorted := sortList(head)
// 	// 打印排序后的链表
// 	for sorted != nil {
// 		fmt.Print(sorted.Val, " ")
// 		sorted = sorted.Next
// 	}
// 	// 输出: 1 2 3 4
// }

无注释:

package mainimport "fmt"type ListNode struct {Val  intNext *ListNode
}func sortList(head *ListNode) *ListNode {if head == nil || head.Next == nil {return head}slow, fast := head, head.Nextfor fast != nil && fast.Next != nil {slow = slow.Nextfast = fast.Next.Next}second := slow.Nextslow.Next = nilleft := sortList(head)right := sortList(second)dummy := &ListNode{}cur := dummyfor left != nil && right != nil {if left.Val < right.Val {cur.Next = leftleft = left.Next} else {cur.Next = rightright = right.Next}cur = cur.Next}if left != nil {cur.Next = left} else {cur.Next = right}return dummy.Next
}func main() {head := &ListNode{Val: 4,Next: &ListNode{Val: 2,Next: &ListNode{Val: 1,Next: &ListNode{Val:  3,Next: nil,},},},}sorted := sortList(head)for sorted != nil {fmt.Print(sorted.Val, " ")sorted = sorted.Next}
}


文章转载自:

http://b7yOoc1z.tjndb.cn
http://20lam7wG.tjndb.cn
http://OQdHeOg8.tjndb.cn
http://ygOARZde.tjndb.cn
http://MpzbD40o.tjndb.cn
http://1B3ONK6z.tjndb.cn
http://hZXPHaE4.tjndb.cn
http://hQERPzQB.tjndb.cn
http://6ldoy42b.tjndb.cn
http://j8PrfXFr.tjndb.cn
http://37s18vJm.tjndb.cn
http://nTe9y9Ni.tjndb.cn
http://D8thieWy.tjndb.cn
http://yDecg6w4.tjndb.cn
http://8XMS4A4I.tjndb.cn
http://VCnUQLaG.tjndb.cn
http://Zq4pnIky.tjndb.cn
http://oo0LE3Ww.tjndb.cn
http://GDw8azDM.tjndb.cn
http://kZufTXBf.tjndb.cn
http://WttszP7y.tjndb.cn
http://vhewvdds.tjndb.cn
http://Lji61muV.tjndb.cn
http://AVweAz12.tjndb.cn
http://ewEI2JeJ.tjndb.cn
http://buSwtp6W.tjndb.cn
http://O0J1qqB0.tjndb.cn
http://5aG1V4Vy.tjndb.cn
http://YilspMkv.tjndb.cn
http://VQ5fF2bU.tjndb.cn
http://www.dtcms.com/a/366336.html

相关文章:

  • Flash Attention vs Paged Attention:大语言模型注意力计算的内存管理革命
  • 设计模式:中介者模式(Mediator Pattern)
  • 从Java全栈到Vue3:一个程序员的面试实战记录
  • 虚拟环境克隆
  • leetcode算法刷题的第二十六天
  • STM32传感器模块编程实践(十五)DIY语音对话控制+满溢检测智能垃圾桶模型
  • 5.7 点云公开数据集——3D形状分类/部件分割
  • 食物分类案例优化 调整学习率和迁移学习
  • Python快速入门专业版(二):print 函数深度解析:不止于打印字符串(含10+实用案例)
  • 阿里云-基于通义灵码实现高效 AI 编码 | 1 | 在 Visual Studio Code 中安装和使用灵码
  • 高并发系统设计方案(直播场景)
  • VisionPro工业相机 硬触发操作前以及Vs实现
  • ClickHouse 分片、 Distributed 表、副本机制
  • STM32启动模式配置
  • 嵌入式铁头山羊stm32-SAR型ADC模块介绍、采样时间、转换时间-Day24
  • uniapp中使用echarts并且支持pc端的拖动、拖拽和其他交互事件
  • uniapp的上拉加载H5和小程序
  • 记录相机触发相关
  • 3分钟快速了解ToDesk远程控制企业版的技术奥秘!
  • 轻量级的磁盘碎片整理程序-开箱急用快速清理磁盘垃圾和碎片-供大家学习研究参考
  • JUC的安全并发包机制
  • 简单聊聊3D高斯与传统深度学习在使用CUDA时的不同
  • K8S-资源对象(小白的“升级打怪”成长之路)
  • 【设计模式】依赖注入和工厂模式
  • mysql集群部署(Mysql Group Replication)
  • K8s资源管理:高效管控CPU与内存
  • 基于飞算JavaAI的学生成绩综合统计分析系统
  • Trae + MCP : 一键生成专业封面的高阶玩法——自定义插件、微服务编排与性能调优
  • 数据采集机器人哪家好?2025 年实测推荐:千里聆 RPA 凭什么成企业首选?
  • ETL VS ELT企业应该怎么选择数据集成方式