Sort a linked list in O(n log n) time using constant space complexity.
Example 1:
Input: 4->2->1->3 Output: 1->2->3->4
Example 2:
Input: -1->5->3->4->0 Output: -1->0->3->4->5
解题思路:
本题还是有点意思的,虽然只是看上去只是链表排序,但是要求时间复杂度O(n log n),空间复杂度O(1)。需要用到归并排序。一般而言,归并排序的空间复杂度为n,但是本题为链表,可以控制在常数级别。
在做本题之前,建议先看看这篇https://blog.csdn.net/qq_41562704/article/details/89429773如何合并两个有序的链表。
归并排序先将节点每两个一组排序,再将每两个小组(即4个节点)排序;但是本题并非数组存储,无法直接到达下一组的起点,所以本题需要用递归,将链表平均分为两半,直到只有单个节点,将两半链表合并(用链接中的方法),根据递归性质,合并的时候,两半的链表都各自排序好的。另外还有一个问题,如何找到链表的中点,这里用到快慢指针法,在判断链表中是否有环的时候常用到。
class Solution {
public:
ListNode* sortList(ListNode* head) {
return head == nullptr ? head : mergeSort(head);
}
private:
ListNode* mergeSort(ListNode* node){
if(node->next == nullptr)
return node;
ListNode *fast = node, *slow = node, *mid;
while(fast != nullptr && fast->next != nullptr){
mid = slow;
slow = slow->next;
fast = fast->next->next;
}
mid->next = nullptr;
ListNode* L = mergeSort(node);
ListNode* R = mergeSort(slow);
return merge(L, R);
}
ListNode* merge(ListNode* L, ListNode* R){
if(L == nullptr)
return R;
if(R == nullptr)
return L;
if(L->val <= R->val){
L->next = merge(L->next, R);
return L;
}
else{
R->next = merge(L, R->next);
return R;
}
}
};