news 2026/4/15 14:47:30

148. 排序链表

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
148. 排序链表

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 * 104]
  • -105 <= Node.val <= 105

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

📝 核心笔记:排序链表 (Sort List)

1. 核心思想 (一句话总结)

“分而治之:先把长链表切成两半,分别排好序,再把两条有序链表拉链式合并。”

这是LC 21 (合并两个有序链表)LC 876 (链表的中间结点)的集大成者。

  • 分 (Divide):利用快慢指针找到中点,将链表断开成两条。
  • 治 (Conquer):递归地对这两条子链表进行排序。
  • 合 (Combine):将排好序的子链表合并(归并)。
2. 算法流程 (递归三步曲)
  1. 找中点并断链 (middleNode)
    • 使用快慢指针。
    • 关键点:必须记录slow的前驱节点pre。找到中点后,执行pre.next = null
    • 如果不切断,链表还是连在一起的,递归就会陷入死循环 (StackOverflow)。
  1. 递归排序 (sortList)
    • 对左半部分 (head) 递归。
    • 对右半部分 (head2) 递归。
    • 基准条件:如果链表为空或只有一个节点,直接返回。
  1. 合并 (mergeTwoLists)
    • 将两个有序链表合并为一个(直接复用之前的逻辑)。
🔍 代码回忆清单
// 题目:LC 148. Sort List class Solution { public ListNode sortList(ListNode head) { // 1. 递归终止条件 (Base Case) // 0 个或 1 个节点本身就是有序的 if (head == null || head.next == null) { return head; } // 2. 找中点并【切断】 // 这里复用了"寻找中点"的逻辑,但多了一步"切断" ListNode head2 = middleNode(head); // 3. 分治 (Divide) head = sortList(head); // 排序前半段 head2 = sortList(head2); // 排序后半段 // 4. 合并 (Combine) // 复用合并有序链表的逻辑 return mergeTwoLists(head, head2); } // 辅助 1: 找中点 + 断链 private ListNode middleNode(ListNode head) { ListNode pre = head; // 用于断后路 ListNode slow = head; ListNode fast = head; while (fast != null && fast.next != null) { pre = slow; // pre 紧跟 slow 后面 slow = slow.next; fast = fast.next.next; } // 核心操作:把链表一分为二 // 此时 head~pre 是前半段,slow~end 是后半段 pre.next = null; return slow; // 返回后半段的头 } // 辅助 2: 合并有序链表 (标准的 LC 21) private ListNode mergeTwoLists(ListNode list1, ListNode list2) { ListNode dummy = new ListNode(); ListNode cur = dummy; while (list1 != null && list2 != null) { if (list1.val < list2.val) { cur.next = list1; list1 = list1.next; } else { cur.next = list2; list2 = list2.next; } cur = cur.next; } cur.next = list1 != null ? list1 : list2; return dummy.next; } }
⚡ 快速复习 CheckList (易错点 & 进阶)
  • [ ]为什么必须用pre.next = null
    • 面试高频点。这是链表归并排序和数组归并排序最大的不同。数组是通过下标计算划分区域的,物理上不用切断;链表是通过指针连接的,如果不物理切断,head顺着走还能走到head2,逻辑就乱了,且会导致无限递归。
🖼️ 数字演练

链表:4 -> 2 -> 1 -> 3

  1. Split 1:
    • Slow=1,Pre=2. 断开 2->1.
    • Left:4->2, Right:1->3.
  1. Left Recursion (4->2):
    • Slow=2,Pre=4. 断开 4->2.
    • Left:4, Right:2.
    • Merge:2->4.
  1. Right Recursion (1->3):
    • Slow=3,Pre=1. 断开 1->3.
    • Left:1, Right:3.
    • Merge:1->3.
  1. Final Merge (2->4, 1->3):
    • Compare 2, 1 -> 选 1.
    • Compare 2, 3 -> 选 2.
    • Compare 4, 3 -> 选 3.
    • Compare 4, null -> 选 4.
    • Result:1 -> 2 -> 3 -> 4.
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/8 22:36:13

潮玩一番赏小程序开发玩法分析(附技术落地要点)

随着潮玩经济持续升温&#xff0c;一番赏凭借“梯度奖池100%中奖稀缺性刺激”的核心逻辑&#xff0c;成为小程序开发的热门赛道。不同于普通盲盒的单一抽奖模式&#xff0c;一番赏小程序的核心竞争力在于玩法设计&#xff0c;而玩法落地的关键是技术适配与合规管控。本文立足CS…

作者头像 李华
网站建设 2026/4/8 18:52:26

离谱!裁员裁出新高度了。。。

还记得今年某大厂公布了2024年财报&#xff0c;数据显示&#xff0c;截至2024年12月31日&#xff0c;员工总数为194320人&#xff0c;而截至2023年12月31日&#xff0c;这一数字为219260人。这也意味着&#xff0c;过去一年减员了近24940人。这不是个例——在互联网全面进入存量…

作者头像 李华
网站建设 2026/4/12 14:29:38

php BC MATH扩展函数巧妙进行财务金额四舍五入

结论&#xff1a;bcadd函数操作 0.5 能够实现“四舍五入”。✅ 核心原理&#xff1a;加 0.5 的作用 在十进制中&#xff0c;“四舍五入”的本质是&#xff1a; 如果小数部分 大于等于 0.5&#xff0c;则向上取整&#xff1b;如果小数部分 小于 0.5&#xff0c;则向下取整。 通过…

作者头像 李华
网站建设 2026/4/14 15:46:37

多智能体协作封神!MultiAgentPPT让高质量PPT生成效率暴涨10倍

相信每个职场人都有过被PPT支配的恐惧&#xff1a;为了一份汇报&#xff0c;翻遍十几份资料找数据&#xff0c;熬到半夜梳理逻辑结构&#xff0c;反复调整排版格式&#xff0c;最后还可能因为内容不全面、逻辑不清晰被打回重改。学生党做课题报告、创业者准备融资演示、市场人员…

作者头像 李华
网站建设 2026/4/14 12:34:59

一文讲透|专科生必备的AI论文软件 —— 千笔·专业学术智能体

你是否曾为论文选题发愁&#xff0c;绞尽脑汁却无从下手&#xff1f;是否在深夜面对空白文档&#xff0c;思绪枯竭、无从下笔&#xff1f;又或者&#xff0c;反复修改却总对表达不满意&#xff0c;查重率高得让人心慌&#xff1f;专科生的论文之路本就充满挑战&#xff0c;而千…

作者头像 李华