Sort List
Sort a linked list in O(n log n) time using constant space complexity.
思路:
其实可以做一个快速排序或者merge排序之类的。但是这里的linked list是单向的,所以普通的快排办不到。不过仍然可以借用快速排序的思路,每次把链表分为三个部分:小于pivot,等于pivot和大于pivot,然后对小于大于pivot的部分进行排序。最后把三个部分结合起来。这样就是一个O(nlogn)的算法了。
题解:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
struct RList
{
ListNode* head;
ListNode* last;
size_t size;
RList() : head (nullptr), last (nullptr), size (0)
{}
void Append (ListNode* ln)
{
if (head == nullptr)
head = last = ln;
else
{
last->next = ln;
last = last->next;
}
++size;
}
void Combine (RList& l)
{
if (head == nullptr)
{
head = l.head;
last = l.last;
}
else if (l.head != nullptr)
{
last->next = l.head;
last = l.last;
}
size += l.size;
l.size = 0;
l.head = l.last = nullptr;
}
};
RList sortRList(RList rl)
{
if (rl.size == 0)
return rl;
int pivot_value = rl.head->val;
RList lpivot, pivot, rpivot;
ListNode* iter = rl.head;
while(iter != nullptr)
{
if (iter->val > pivot_value)
rpivot.Append(iter);
else if (iter->val == pivot_value)
pivot.Append(iter);
else
lpivot.Append(iter);
iter = iter->next;
}
if (rpivot.last != nullptr) rpivot.last->next = nullptr;
if (pivot.last != nullptr) pivot.last->next = nullptr;
if (lpivot.last != nullptr) lpivot.last->next = nullptr;
if (rpivot.size > 1) rpivot = sortRList(rpivot);
if (lpivot.size > 1) lpivot = sortRList(lpivot);
lpivot.Combine(pivot);
lpivot.Combine(rpivot);
return lpivot;
}
ListNode* sortList (ListNode* head)
{
if (head == nullptr)
return nullptr;
ListNode* last = head;
int size = 1;
while(last->next != nullptr) last = last->next, ++size;
RList rl;
rl.head = head;
rl.last = last;
rl.size = size;
rl = sortRList(rl);
return rl.head;
}
};