Sort a linked list in O(nlogn) time using constant space complexity.

When it comes to the algorithm that can sort in O(nlogn), it should be Merge sort, Quick sort, Heap sort. The difficult part in this question is the space complexity. If you choose recursive, the program stack will exceed the requirement and might lead to stack overflow. If you use Top-down merge sort, you will use another recursive in your program.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
/**
* https://goo.gl/xgNMT4
* Merge sort use bottom-up policy,
* so Space Complexity is O(1)
* Time Complexity is O(NlgN)
* stable sort
*/

class Solution {
public:
ListNode *sortList(ListNode *head) {
if(!head || !(head->next)) return head;

//get the linked list's length
ListNode* cur = head;
int length = 0;
while(cur){
length++;
cur = cur->next;
}

ListNode dummy(0);
dummy.next = head;
ListNode *left, *right, *tail;
for(int step = 1; step < length; step <<= 1){
cur = dummy.next;
tail = &dummy;
while(cur){
left = cur;
right = split(left, step);
cur = split(right,step);
tail = merge(left, right, tail);
}
}
return dummy.next;
}
private:
/**
* Divide the linked list into two lists,
* while the first list contains first n ndoes
* return the second list's head
*/
ListNode* split(ListNode *head, int n){
//if(!head) return NULL;
//1. point to the position that want to spilt
//2. separate two linked list, which are from start->head, second
for(int i = 1; head && i < n; i++) head = head->next;

if(!head) return NULL;
ListNode *second = head->next;
head->next = NULL; //end the list
return second;
}
/**
* merge the two sorted linked list l1 and l2,
* then append the merged sorted linked list to the node head
* return the tail of the merged sorted linked list
*/
ListNode* merge(ListNode* l1, ListNode* l2, ListNode* head){
ListNode *cur = head;
while(l1 && l2){
if(l1->val > l2->val){
cur->next = l2;
cur = l2;
l2 = l2->next;
}
else{
cur->next = l1;
cur = l1;
l1 = l1->next;
}
}
cur->next = (l1 ? l1 : l2);
while(cur->next) cur = cur->next;
return cur;
}
};

Reference:
https://goo.gl/xgNMT4
https://goo.gl/zgWtLT
https://goo.gl/JY6o7o