Sort a linked list in O(n log n) time using constant space complexity.
/**
* 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 == nullptr || head->next == nullptr) return head;
ListNode * pivot = head, * small = nullptr, * large = nullptr, *sp = nullptr, *lp = nullptr;
head = head->next;
while(head) {
if(head->val < pivot->val) {
if (small == nullptr) small = head;
else sp->next = head;
sp = head;
} else {
if (large == nullptr) large = head;
else lp->next = head;
lp = head;
}
head = head->next;
}
if(sp) sp->next = nullptr;
if(lp) lp->next = nullptr;
// sort the sub list.
sp = sortList(small);
lp = sortList(large);
// merge the sub list.
if(sp) {
head = sp;
// seek to the last node.
while(sp->next)
sp = sp->next;
sp->next = pivot;
} else {
head = pivot;
}
pivot->next = lp;
return head;
}
};
if we only change the value. it will improve a some time complexity.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
private:
ListNode * partition(ListNode * head, ListNode * tail) {
if(head == tail || head->next == nullptr) return head;
int pivot = head->val;
ListNode * slow = head, *fast = head->next;
while(fast && fast != tail) {
if (fast->val < pivot) {
slow = slow->next;
swap(slow->val, fast->val);
}
fast = fast->next;
}
// swap the pivot
swap(slow->val, head->val);
return slow;
}
void quicksort(ListNode * head, ListNode * tail) {
if(head == tail || head->next == nullptr) return;
ListNode * pivot = partition(head, tail);
quicksort(head, pivot);
quicksort(pivot->next, tail);
}
public:
ListNode* sortList(ListNode* head) {
quicksort(head, nullptr);
return head;
}
};
if we do a non-recursive merge sort. the effeciency will be time O(NlogN), and the space with O(1).
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
private:
// from head->@->@->@->null to
// head->@->@->null current->@->null
ListNode * cut(ListNode * head, int n) {
if (head == nullptr) return head;
ListNode * p = head;
while(--n && p) {
p = p->next;
}
if (p == nullptr) return nullptr;
ListNode * next = p->next;
// cut the current node
p->next = nullptr;
return next;
}
// merge two linklist and return the header
ListNode * merge(ListNode * l, ListNode * r) {
ListNode dummyHead(0);
ListNode * p = &dummyHead;
while(l && r) {
if(l->val < r->val) {
p->next = l;
p = l;
l = l->next;
} else {
p->next = r;
p = r;
r = r->next;
}
}
p->next = l ? l : r;
return dummyHead.next;
}
public:
ListNode* sortList(ListNode* head) {
ListNode dummyHead(0);
dummyHead.next = head;
int length = 0;
while(head) {
head = head->next;
++length;
}
for(int size = 1; size < length; size <<= 1) {
ListNode * cur = dummyHead.next;
ListNode * p = &dummyHead;
while(cur) {
ListNode * left = cur;
ListNode * right = cut(cur, size);
cur = cut(right, size);
p->next = merge(left, right);
// seek to the end.
while(p->next) {
p = p->next;
}
}
}
return dummyHead.next;
}
};