Lintcode 98. 链表排序
题目描述:在 O(nlogn) 时间复杂度和常数级的空间复杂度下给链表排序。
O(nlogn)时间复杂度的排序算法的话,快速排序,归并排序,堆排序都能达到。
另外,对于空间复杂度的话,普遍来看三者中只有快速排序能达到O(1),堆排序会用到堆空间,归并排序在数组中会需要额外的O(n)空间用于拷贝,但是在链表中的话归并排序可以不需要这个O(n)空间,因为链表的操作我们只需要改变next指针就可以。
下面给出归并排序的代码实现,这里归并的方法简单点。快速排序也可以实现,之后找时间再实现吧。
// 归并排序
/**
* Definition of singly-linked-list:
* class ListNode {
* public:
* int val;
* ListNode *next;
* ListNode(int val) {
* this->val = val;
* this->next = NULL;
* }
* }
*/
class Solution {
public:
/**
* @param head: The head of linked list.
* @return: You should return the head of the sorted linked list, using constant space complexity.
*/
ListNode * sortList(ListNode * head) {
if (nullptr == head || nullptr == head->next) {
return head;
}
ListNode *mid = findMiddle(head);
ListNode *right = sortList(mid->next);
mid->next = nullptr;
ListNode *left = sortList(head);
return merge(left, right);
}
private:
//寻找中间节点mid
ListNode *findMiddle(ListNode *head) {
ListNode *slow = head;
ListNode *fast = head->next;
while (nullptr != fast && nullptr != fast->next) {
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
// merge
ListNode *merge(ListNode *head1, ListNode *head2) {
ListNode *dummy = new ListNode(0);
ListNode *tail = dummy;
while (nullptr != head1 && nullptr != head2) {
if (head1->val < head2->val) {
tail->next = head1;
head1 = head1->next;
} else {
tail->next = head2;
head2 = head2->next;
}
tail = tail->next;
}
if (nullptr != head1) {
tail->next = head1;
} else {
tail->next = head2;
}
ListNode *head = dummy->next;
delete dummy;
return head;
}
};