Sort a linked list in O(n log n) time using constant space complexity.
We can use merge sort to sort linked list. Split the list into single elements and merge them recursively.
C++ Code:
/*
* func: merge_sort_list
* goal: merge two sorted list into one
* @param left_part: one sorted linked list
* @param right_part: another sorted linked list
* return: new head after merge
*/
ListNode *merge_sort_list(ListNode *left_part, ListNode *right_part){
ListNode *left_iter = left_part;
ListNode *right_iter = right_part;
ListNode *new_head = nullptr;
ListNode *new_iter = nullptr;
while(left_iter && right_iter){
ListNode *curr = nullptr;
if(left_iter->val >= right_iter->val){
curr = right_iter;
right_iter = right_iter->next;
}else{
curr = left_iter;
left_iter = left_iter->next;
}
if(new_head == nullptr){
new_head = curr;
new_iter = curr;
}else{
new_iter->next = curr;
new_iter = new_iter->next;
}
}
if(left_iter){
if(new_head == nullptr){
new_head = left_iter;
new_iter = left_iter;
}else{
new_iter->next = left_iter;
new_iter = new_iter->next;
}
}
if(right_iter){
if(new_head == nullptr){
new_head = right_iter;
new_iter = right_iter;
}else{
new_iter->next = right_iter;
new_iter = new_iter->next;
}
}
return new_head;
}
/*
* func: sort_list
* goal: sort the list in o(n logn) times
* @param head: head node of the list
* return: new head
*/
ListNode *sort_list(ListNode *head){
ListNode *slow = head;
ListNode *fast = head;
while(fast->next && fast->next->next){
slow = slow->next;
fast = fast->next->next;
}
ListNode *right = slow->next;
slow->next = nullptr;
ListNode *left_part = sort_list(head);
ListNode *right_part = sort_list(right);
ListNode *new_head = merge_sort_list(left_part, right_part);
return new_head;
}
Python Code:
# func: merge sort for linked list
# @param head: start sorting node
# @param length: length of the list to be sorted
# return: new head
def merge_sort_list(head, length):
if length == 0 or length == 1:
return head
prev = head
for _ in xrange(length/2 - 1):
prev = prev.next
curr = prev.next
prev.next = None
left_part = merge_sort_list(head, length/2)
right_part = merge_sort_list(curr, length - length/2)
left_iter = left_part
right_iter = right_part
new_head = None
new_iter = None
while left_iter and right_iter:
if left_iter.val >= right_iter.val:
curr = right_iter
right_iter = right_iter.next
else:
curr = left_iter
left_iter = left_iter.next
if not new_head:
new_head = curr
new_iter = curr
else:
new_iter.next = curr
new_iter = new_iter.next
if left_iter:
if not new_head:
new_head = left_iter
else:
new_iter.next = left_iter
if right_iter:
if not new_head:
new_head = right_iter
else:
new_iter.next = right_iter
return new_head
# func: sort link list in O(n logn)
# @param root: head node
# @return: new head node
def sort_list(head):
length = 0
iter = head
while iter:
length += 1
iter = iter.next
return merge_sort_list(head, length)
No comments:
Post a Comment