描述
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
进阶:
你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?
分析
时间复杂度是 O(n \log n)O(nlogn) 的排序算法包括归并排序、堆排序和快速排序(快速排序的最差时间复杂度是 O(n^2)),其中最适合链表的排序算法是归并排序。
- 归并排序:每次切分成两半,直到只剩一个,然后按顺序合并分割后的两半,直到合成完整。
- 使用快慢指针定位一个链表的中心点,获得后半段的起始结点
- 一直递归把链表切分成长度相等的两半,直到长度为1
- 按顺序合并两个链表,直到合并完整
class Solution {
public ListNode sortList(ListNode head) {
if(head == null || head.next == null){
return head;
}
ListNode fast = head.next;
ListNode slow = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
}
ListNode newHead = slow.next;
slow.next = null;
ListNode slowHead = sortList(head);
ListNode fastHead = sortList(newHead);
ListNode mergeHead = new ListNode(0);
ListNode cur = mergeHead;
while(fastHead != null && slowHead != null){
if(fastHead.val > slowHead.val){
cur.next = slowHead;
slowHead = slowHead.next;
} else{
cur.next = fastHead;
fastHead = fastHead.next;
}
cur = cur.next;
}
if(fastHead != null){
cur.next = fastHead;
}
if(slowHead != null){
cur.next = slowHead;
}
return mergeHead.next;
}
}