题目链接
题目描述
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
进阶:
- 你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?
示例 1:
输入:head = [4,2,1,3]
输出:[1,2,3,4]
示例 2:
输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]
示例 3:
输入:head = []
输出:[]
提示:
链表中节点的数目在范围 [0, 5 * 104] 内
-105 <= Node.val <= 105
思路
使用自顶向下归并排序解决,由于是链表,要获取中间结点可以采用快慢指针的方法,同时每次mergesort之后都需要返回一个头指针,否则归并时不知道该从哪个位置开始。
但是由于使用了递归,空间复杂度为O(logn),达不到常数级别。
代码如下:
class Solution {
public:
ListNode* sortList(ListNode* head) {
if(!head)
return NULL;
return mergesort(head);
}
ListNode* mergesort(ListNode *head){
if(!head->next)
return head;
ListNode *slow=head,*fast=head;
while(fast->next&&fast->next->next){
slow=slow->next;
fast=fast->next->next;
}
ListNode *tmp=slow->next;
slow->next=NULL;
ListNode *left=mergesort(head);
ListNode *right=mergesort(tmp);
return merge(left,right);
}
ListNode* merge(ListNode *p1,ListNode *p2){
ListNode *head=new ListNode(0),*ans=head;
while(p1&&p2){
if(p1->val<p2->val){
head->next=p1;
p1=p1->next;
}
else{
head->next=p2;
p2=p2->next;
}
head=head->next;
}
while(p1){
head->next=p1;
p1=p1->next;
head=head->next;
}
while(p2){
head->next=p2;
p2=p2->next;
head=head->next;
}
return ans->next;
}
};