题目描述
给你链表的头结点head,请将其按照升序排列并返回排序后的链表。
解答一:使用递归法进行归并排序
- 分割环节:找到当前链表的中点,并从中点将链表断开以方便在下次递归的时候cut,链表的片段拥有正确的边界
- 我们使用fast, slow快慢双指针算法,奇数个节点找到中点,偶数个节点找到中心节点左边的节点,这时候快指针走到结束位置。
public ListNode sortList(ListNode head) {
return head == null ? null : mergeSort(head);
}
private ListNode mergeSort(ListNode head){
if(head.next == null){
return head;
}
ListNode p = head,q =head , pre= null;
while(q != null && q.next != null){
pre = p;
p = p.next;
q = q.next.next;
}
//找到中点之后执行slow.next == null 将链表切断
pre.next = null;
//将链表切割成左半部分和右半部分
//head是左半部分
//p是我们右半部分的开始
ListNode l = mergeSort(head);
ListNode r = mergeSort(p);
return merge(l,r);
}
ListNode merge(ListNode l,ListNode r){
//合并就可以了
ListNode dummyHead = new ListNode(0);
ListNode cur = dummyHead;
while(l != null && r != null){
if(l.val <= r.val){
cur.next = l;
cur = cur.next;
l = l.next;
}else{
cur.next = r;
cur = cur.next;
r = r.next;
}
}
if(l != null){
cur.next = l;
}
if(r != null){
cur.next = r;
}
return dummyHead.next;
}
}