在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:输入: 4->2->1->3 输出: 1->2->3->4
题解:
- O(nlogn)的排序有 快排、堆排序、归并排序
- 快排需要双指针不满足,堆排序难以建堆且空间复杂度不满足要求,选择归并排序
- 使用快慢指针将链表一分为二,对左右两个链表分别排序,再mergeList将右链表插入左链表,递归进行
- 递归至只剩余1个结点返回,2个结点时手动排序
class Solution {
public ListNode sortList(ListNode head) {
//O(nlogn)快排、堆排序、归并排序
//快排需要双指针不满足,堆排序空间复杂度过高
if(head==null || head.next==null){
return head;
}
if(head.next.next == null){
//只有两个结点排序
if(head.val<head.next.val){
return head;
}
ListNode p = head;
ListNode q = head.next;
head.next = null;
q.next = p;
return q;
}
//超过两个结点快慢指针分割链表
ListNode fast = head;
ListNode slow = head;
while(fast.next!=null && fast.next.next!=null){
fast = fast.next.next;
slow = slow.next;
}
//分解成左右链表
fast = slow.next;
slow.next = null;
ListNode left = sortList(head);
ListNode right = sortList(fast);
//合并左右链表,右链表插入左链表
ListNode l_list = new ListNode(-1);
l_list.next = left;
left = l_list;
while(left!=null && right!=null){
ListNode cur = left.next;
if(cur == null){
//处理尾结点
left.next = right;
break;
}else{
if(right.val <cur.val){
ListNode tmp = right.next;
right.next = left.next;
left.next = right;
right = tmp;
}
left = left.next;
}
}
return l_list.next;
}
}