148. 排序链表

中等 含交互动画

学完这道你应该能: 说清它为什么用「归并排序」,而不是死记步骤; 合上页面,自己默写出核心代码; 用 30 秒把思路讲清楚。

AI 私教 · 就着本题动画讲
卡住了不用硬扛,按 8 步把这题真正走通。
从读题、试解、找法到手写代码,边问边打勾,适合第一次系统学算法的同学。

题目描述

在 O(n log n) 时间、尽量 O(1) 额外空间内排序链表。

输入 = 4→2→1→3
输出 = 1→2→3→4

思路解析

关键不是背模板,而是看懂为什么这题适合链表 · 归并排序

1. 快慢指针找到中点:快慢指针找到中点

2. 从中点断开,分成左右两段:从中点断开,分成左右两段

3. 递归排序左半段:递归排序左半段

4. 递归排序右半段:递归排序右半段

5. 两段各自有序后开始合并:两段各自有序后开始合并

6. 比较两个头节点,小的接到结果后面:比较两个头节点,小的接到结果后面

7. 不断接小节点:不断接小节点

8. 合并完成得到有序链表:合并完成得到有序链表

把这句话记住,下次遇到同类题,就能更快选出方向。

用一个小问题检查自己是不是真的懂了。

参考代码(Python)

Python
1class Solution:
2    def sortList(self, head):
3        if not head or not head.next:
4            return head
5        slow, fast = head, head.next
6        while fast and fast.next:
7            slow = slow.next
8            fast = fast.next.next
9        mid = slow.next
10        slow.next = None
11        left = self.sortList(head)
12        right = self.sortList(mid)
13        return self.merge(left, right)
14    def merge(self, a, b):
15        dummy = tail = ListNode(0)
16        while a and b:
17            if a.val < b.val:
18                tail.next, a = a, a.next
19            else:
20                tail.next, b = b, b.next
21            tail = tail.next
22        tail.next = a or b
23        return dummy.next

复杂度分析

  • 时间复杂度:O(n log n) —— 每个核心状态按算法要求处理固定次数
  • 空间复杂度:O(log n) —— 只保存必要的辅助结构或递归栈

套路模板

模板不是死背,而是提醒你写代码前先把状态、转移和边界排好。

Python
1# 链表 · 归并排序 通用检查表
2# 1. 定义状态/指针/容器
3# 2. 每轮只做一个清晰动作
4# 3. 更新答案并处理边界

易错点

  • 错误写法:用数组排序后重建正确写法:链表排序的核心是切半和原地合并(数组法绕开了链表训练点)
  • 错误写法:只按样例推代码正确写法:先写清状态含义和边界条件(样例太少,隐藏用例专打边界)
  • 错误写法:变量名和动画不一致正确写法:代码变量沿用动画里的核心名字(学习时最怕脑内维护两套概念)

以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握

下一题 →25. K 个一组翻转链表 ← 返回题库