对链表进行归并排序:
归并排序分为自顶向下(将整个拆成两半,利用递归分别对两半进行排序,然后再对排好的两半进行合并,层层递归直到元素大小为1——不可拆分再返回其本身),合并时,对两半从头到尾的方式进行合并(双指针法,指针交替前行,比较两指针指向元素的大小)
还可以自底向上,我一般用自顶向下(二分+递归)
归并排序的时间复杂度为 O(nlogn)
难度中等1082
给你链表的头结点 head
,请将其按 升序 排列并返回 排序后的链表 。
进阶:
- 你可以在
O(n log n)
时间复杂度和常数级空间复杂度下,对链表进行排序吗?
示例 1:
输入:head = [4,2,1,3] 输出:[1,2,3,4]
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
//归并排序
class Solution {
public ListNode sortList(ListNode head) {
if(head==null||head.next==null) return head;
ListNode slow=head,fast=head;
while(true){
if(fast.next==null||fast.next.next==null) break;
fast=fast.next.next;
slow=slow.next;
}
//slow 为左中位
ListNode r= sortList(slow.next);
slow.next=null;
ListNode l= sortList(head);
return merge(l,r);
}
public ListNode merge(ListNode l,ListNode r){
ListNode head=new ListNode(-1);
ListNode p=head;
while(l!=null&&r!=null){
if(l.val<=r.val){
p.next=l;
l=l.next;
p=p.next;
}else{
p.next=r;
r=r.next;
p=p.next;
}
}
if(r!=null) p.next=r;
if(l!=null) p.next=l;
return head.next;
}
}