题目链接
思想
-
分割 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;
}
}
标签:head,slow,ListNode,next,链表,排序,LeetCode,left
From: https://www.cnblogs.com/shixuanliu/p/17015854.html