【归并排序】【链表】LeetCode 148. 排序链表
题目链接
思想
-
分割 cut 环节: 找到当前链表中点,并从中点将链表断开(以便在下次递归 cut 时,链表片段拥有正确边界)
-
我们使用 fast,slow 快慢双指针法,奇数个节点找到中点,偶数个节点找到中心左边的节点。
-
找到中点 slow 后,执行 slow.next = None 将链表切断。
-
递归分割时,输入当前链表左端点 head 和中心节点 slow 的下一个节点 mid(因为链表是从 slow 切断的)。
-
cut 递归终止条件: 当head.next == None时,说明只有一个节点了,直接返回此节点。
-
-
合并 merge 环节: 将两个排序链表合并,转化为一个排序链表。
-
双指针法合并,建立辅助ListNode dummy 作为头部。
-
设置两指针 left, right 分别指向两链表头部,比较两指针处节点值大小,由小到大加入合并链表头部,指针交替前进,直至添加完两个链表。
-
返回辅助ListNode dummy 作为头部的下个节点 dummy.next。
-
时间复杂度 O(l + r),l, r 分别代表两个链表长度。
-
-
当题目输入的 head == None 时,直接返回None。
代码
class Solution {
public ListNode sortList(ListNode head) {
// end condition
if (head == null || head.next == null) {
return head;
}
// find the middle node
ListNode slow = head;
ListNode fast = head.next;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
ListNode mid = slow.next;
// split the list into two parts
slow.next = null;
ListNode left = sortList(head);
ListNode right = sortList(mid);
// sort the two parts
ListNode dummy = new ListNode(0);
ListNode p = dummy;
while (left != null && right != null) {
if (left.val < right.val) {
p.next = left;
left = left.next;
} else {
p.next = right;
right = right.next;
}
p = p.next;
}
// merge the two parts
if (left != null) {
p.next = left;
} else {
p.next = right;
}
return dummy.next;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?