Sort a singly-linked list is easy with quick sort and merge sort algorithm.
The worst case run time of quick sort is O(n ^ 2). Whereas merge sort is a stable sort with O(n logn) complexity, and it is a in-place algorithm to sort the linked list.
This code implements a quick sort alogirthm with python. Got an AC with a simple trick. Because the test data only contains "bad cases" but not the "worst cases".
If there is a test case "[100000, 99999, 99998 ... ... 0]" , my code will take a long time to get the result. Duh...
class Solution:
# @param head, a ListNode
# @return a ListNode
def sortList(self, head):
if not head:
return head
pivot = head
xs = head.next
left, right = self.partition(xs, pivot)
left = self.sortList(left)
right = self.sortList(right)
pivot.next = right
if left:
ptr = left
while ptr.next:
ptr = ptr.next
ptr.next = pivot
return left
else:
return pivot
def partition(self, head, pivot):
left = right = None
leftPtr = rightPtr = None
while head:
if head.val <= pivot.val:
if not left:
left = leftPtr = head
else:
leftPtr.next = head
leftPtr = leftPtr.next
else:
if not right:
right = rightPtr = head
else:
rightPtr.next = head
rightPtr = rightPtr.next
head = head.next
if leftPtr:
leftPtr.next = None
if rightPtr:
rightPtr.next = None
return left, right
Here is the merge-sort version. Merge sort is an easy approach to the result, just divides the linked-list into two, and conquer one by one.
But there is a knack in divide a link-list into two same length sub-lists. You can see it in the code.
/**
* 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 || !head->next) return head;
ListNode *left, *right;
partition(head, left, right);
left = sortList(left);
right = sortList(right);
head = NULL;
ListNode *ptr = NULL;
while (left && right) {
ListNode *now = NULL;
if (left -> val <= right -> val) {
now = left;
left = left -> next;
} else {
now = right;
right = right -> next;
}
if (!head) {
head = now;
ptr = head;
ptr -> next = NULL;
} else {
ptr -> next = now;
ptr = ptr -> next;
}
}
if (left) {
ptr -> next = left;
}
if (right) {
ptr -> next = right;
}
return head;
}
void partition(ListNode *head, ListNode* &left, ListNode* &right)
{
if (!head) {
left = right = NULL;
return;
} else if (!head -> next) {
left = head;
right = NULL;
return;
}
ListNode *a, *b;
a = b = head;
while (true) {
b = b -> next;
if (!b) break;
b = b -> next;
if (!b) break;
a = a -> next;
}
right = a -> next;
a -> next = NULL;
left = head;
}
};