链表排序
1、要求:
Sort a linked list in O(n log n) time using constant space complexity.
2、思路
因为题目要求复杂度为O(nlogn),故可以考虑归并排序的思想。
归并排序的一般步骤为:
1)将待排序数组(链表)取中点并一分为二;
2)递归地对左半部分进行归并排序;
3)递归地对右半部分进行归并排序;
4)将两个半部分进行合并(merge),得到结果。
3、代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
/*
考点:
1. 快慢指针;2. 归并排序。
复杂度分析:
T(n) 拆分 n/2, 归并 n/2 ,一共是n/2 + n/2 = n
/ \ 以下依此类推:
T(n/2) T(n/2) 一共是 n/2*2 = n
/ \ / \
T(n/4) ........... 一共是 n/4*4 = n
一共有logn层,故复杂度是 O(nlogn)
*/
class Solution {
public:
ListNode *sortList(ListNode *head) {
if (!head || !head->next) return head;
ListNode* p = head, *q = head->next; //使用快慢指针寻找中点
while(q && q->next) {
p = p->next;
q = q->next->next;
}
ListNode* left = sortList(p->next); //先后半部分
p->next = NULL;
ListNode* right = sortList(head);
return merge(left, right);
}
ListNode *merge(ListNode *left, ListNode *right) {
ListNode dummy(0);
ListNode *p = &dummy;
while(left && right) {
if(left->val < right->val) {
p->next = left;
left = left->next;
}
else {
p->next = right;
right = right->next;
}
p = p->next;
}
if (left) p->next = left;
if (right) p->next = right;
return dummy.next;
}
};