Problem:
Sort a linked list in O(n log n) time using constant space complexity.
Analysis:
This solution adopts divide-and-conqure method. The implementation is straightforward except some tricks. These tricks are taken here because to avoid the gap of differences between linked-list and array.
Different with linked-list, we can access any element of an array with its index in equal length of time. In more usual cases, we need to compute indices by some formula or relation.This does not apply to the linked-list case. Every time when we need an elmement in a linked-list, we need run a pointer of node of a linked-list from its head to its tail and stop when the key of a node is equal to that we want.This will greatly increase the time cost in the process of recursion. (O(n) time cost) In the solution of this problem, we use three seperately new linked-lists (all of them with two pointers, one to head and the other one to the tail) to store the elements which are smaller/equal/larger to a given value (the value of the head node). This spends O(1) time to get the tail of a linked-list and combine them to the list we need as a return value.
Solution:
C++:
void AddNode(ListNode*& begin, ListNode*& end, ListNode* elem)
{
if(begin == NULL) {
begin = elem;
end = begin;
} else {
end->next = elem;
end = end->next;
}
}
void SortListImpl(ListNode*& begin, ListNode*& end)
{
if(begin == NULL)
return;
ListNode* lessList = NULL;
ListNode* lessList_tail = NULL;
ListNode* equalList = NULL;
ListNode* equalList_tail = NULL;
ListNode* largerList = NULL;
ListNode* largerList_tail = NULL;
int bar = begin->val;
for(ListNode* cur = begin; cur != NULL; ) {
ListNode* temp = cur;
cur = cur->next;
temp->next = NULL;
if(temp->val < bar)
AddNode(lessList, lessList_tail, temp);
else if(temp->val == bar)
AddNode(equalList, equalList_tail, temp);
else
AddNode(largerList, largerList_tail, temp);
}
if(lessList != NULL && lessList != lessList_tail)
SortListImpl(lessList, lessList_tail);
if(largerList != NULL && largerList != largerList_tail)
SortListImpl(largerList, largerList_tail);
if(lessList != NULL)
lessList_tail->next = equalList;
else
lessList = equalList;
equalList_tail->next = largerList;
begin = lessList;
end = largerList != NULL ? largerList_tail : equalList_tail;
}
ListNode *sortList(ListNode *head) {
if(head == NULL || head->next == NULL)
return head;
ListNode* begin = head;
ListNode* end = head;
while(end->next != NULL)
end = end->next;
SortListImpl(begin, end);
return begin;
}
Java
:
Python: