给你链表的头结点 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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
整个题目可以简述为,一个单链表想要在时间复杂度为 O ( n l o g n ) O(n log n) O(nlogn)重完成
对于这样的题目原来的插入排序肯定不符合题目要求了,在单链表排序中,一般推荐归并排序,有自顶向下和自底向上两种策略,我采用的是自定向上的方法
对于自顶向下的策略,主要是先将单链表分段(一般取单链表的中心点,分成左右两段),分成子段后,排序,合并成最后一个完整的单链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
return SortList(head,nullptr);
}
ListNode* SortList(ListNode* head,ListNode* tail){
if(head==nullptr){
return head;
}
if(head->next==tail){
head->next = nullptr;
return head;
}
ListNode* slow = head, *fast = fast;
while(fast!=tail){
slow = slow->next;
fast = fast->next;
if(fast!=tail){
fast = fast->next;
}
}
ListNode* mid = slow;
return merge(SortList(head,mid),SortList(mid,tail));
}
ListNode* merge(ListNode* head1, ListNode* head2){
ListNode* dummy = new ListNode(0);
ListNode* temp = dummy, *temp1 = head1,*temp2=head2;
while(temp1!=nullptr&&temp2!=nullptr){
if(temp1->val<=temp2->val){
temp->next = temp1;
temp1 = temp1->next;
}else{
temp->next = temp2;
temp2 = temp2->next;
}
temp = temp->next;
}
if(temp1!=nullptr){
temp->next = temp1;
}
if(temp2!=nullptr){
temp->next = temp2;
}
return dummy->next;
}
};