## leetcode Question: Sort List

Sort a linked list in*O*(

*n*log

*n*) time using constant space complexity.

### Analysis:

From the post "Common Sorting Algorithms", we know that the sorting algorithms which have O(n log n) complexity are merge sort and quick sort. So in this problem, we can use merge sort to handle!Different from array data, this problem requires good understanding of linked list operations, e.g., split, merge. Before doing this problem, I suggest you first check out the problem "Merge Two Sorted List" and "Linked List Cycle", and also the merge sort algorithm itself. Then the problem becomes pretty straightforward.

Like the merge sort, we can do recursively:

(1) Split the list (slow fast pointers)

(2) sort the first part (merge sort)

(3) sort the second part (merge sort)

(4) merge the two parts (merge two sorted lists)

See the code below for details. In this code, the pointer to the pointer (reference pointer) is used, note that to get the pointer where "ptrRef" points, we can use "*ptrRef".

### Code:

/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: // Merge two sorted list (save as the leetcode Question 54: Merge Two Sorted Lists) ListNode* sortedMerge(ListNode* l1, ListNode* l2){ ListNode* res = new ListNode(0); ListNode* current = res; while (true){ if (!l1){ current->next = l2; break; } if (!l2){ current->next = l1; break; } if (l1->val < l2->val){ current->next = l1; l1 = l1->next; }else{ current->next = l2; l2 = l2->next; } current = current->next; } return res->next; } // Split a list into two parts, using slow/fast pointers void split(ListNode* head, ListNode** aRef, ListNode** bRef){ ListNode* slow; ListNode* fast; if (head==NULL || head->next==NULL){ *aRef = head; *bRef = NULL; }else{ slow = head; fast = head; while (fast!=NULL && fast->next!=NULL){ fast = fast->next->next; if (fast==NULL){break;} // this is important slow = slow->next; } *aRef = head; *bRef = slow->next; slow->next=NULL; } } // MergeSort LinkedList void mergeSort(ListNode** headRef){ ListNode* head = *headRef; ListNode* a; ListNode* b; if (head==NULL || head->next==NULL){ return; } split(head,&a,&b); //split the list mergeSort(&a); //sort the first part mergeSort(&b); //sort the second part *headRef = sortedMerge(a,b); // merge two sorted part } //main function ListNode *sortList(ListNode *head) { mergeSort(&head); return head; } };

This is actually not constant space. When you do recursive, it is (log n) since you define the variables in each iteration.

ReplyDeleteI wonder why so many people ignore the calling stack when doing the recursion.. Is it because it's easier solving it recursively than iteratively ?

ReplyDeleteExcuse for my ads

ReplyDeleteRecursion won't be constant space. An iterative solution can be found here

http://fmarss.blogspot.com/2014/08/leetcode-solution-sort-list.html