Sort a linked list in O(n log n) time using constant space complexity.
After several months, finally this question is fixed. :) . I am checked my blog, oh, it is two months gone. Keep study every day. Keep focus, keep simple.
Ideas: this question need O(nlogn), so what we could use is only O(nlogn) sorting algorithms. like merge sort.
While if we need to use merge sort, we need to split the list into two parts at least. So, we have the divide -conquer-combine.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *sortList(ListNode *head) {
if(head== nullptr || head->next == nullptr)
{
return head;
}
int total = 0;
ListNode *p = head;
ListNode *q = head;
while(p != nullptr)
{
total++;
p = p -> next;
}
p = head;
int count = 0;
ListNode *last = p;
while(count < total/2)
{
count++;
last = p;
p = p -> next;
}
last -> next = NULL;//!important
ListNode *h1 = sortList(p);//
ListNode *h2 = sortList(q);//divide
return MergeSorting(h1, h2);//
}
private:
ListNode *MergeSorting(ListNode *p, ListNode *q)
{
ListNode *TEMP = new ListNode(0);
ListNode *cur = TEMP;
while(p != nullptr && q != nullptr)
{
if(p->val <= q->val)
{
cur->next = p;
p = p -> next;
}
else
{
cur->next = q;
q = q ->next;
}
cur = cur -> next;
}
if(p == nullptr)
{
cur ->next = q;
}
if(q == nullptr)
{
cur -> next = p;
}
cur = TEMP -> next;
delete TEMP;//!important, or can not pass OJ
return cur;
}
};
Note:
- Divide: Divide the n-element sequence to be sorted into two subsequences of n/2 elements each.
- Conquer: Sort the two subsequences recursively using Merge Sort.
- Combine: Merge the two sorted subsequences to produce the sorted answer.