Q:使用常量空间复杂度在O(n log n)时间内对链表进行排序。
解题思路:
- 题目要求时间复杂度最大为O(n*logn),因此我们考虑使用归并排序思想进行排序
- 找到链表中间位置,将链表切成左右两部分;再找到左右两部分的中间位置将链表切断;直到左右部分的链表不能再切分为止;
- 从下至上递归对切好的链表进行排序,即先让子链表有序,再依次向上让子链表间有序,最后使整个链表有序(二路归并)
代码实现:
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode *sortList(ListNode *head) {
if(head==NULL||head->next==NULL)
return head;
ListNode* cur=head;
ListNode* mid=GetMiddle(head); //找到中间节点
ListNode* newhead=mid->next; //断开链表
mid->next=NULL;
return mergesort(sortList(cur),sortList(newhead));
}
ListNode* GetMiddle(ListNode* head) //快慢指针找中间节点
{
if(head==NULL||head->next==NULL)
return head;
ListNode* slow=head;
ListNode* fast=head;
while(fast!=NULL&&fast->next!=NULL&&fast->next->next!=NULL)
{
slow=slow->next;
fast=fast->next->next;
}
return slow;
}
ListNode* mergesort(ListNode* h1,ListNode* h2)
{
ListNode* res=new ListNode(0);
ListNode* cur=res;
ListNode* cur1=h1;
ListNode* cur2=h2;
while(cur1!=NULL&&cur2!=NULL)
{
if(cur1->val<=cur2->val)
{
cur->next=cur1;
cur1=cur1->next;
}
else
{
cur->next=cur2;
cur2=cur2->next;
}
cur=cur->next;
}
if(cur1==NULL) //防止cur1或者cur2还有剩余节点
cur->next=cur2;
else
cur->next=cur1;
return res->next;
}
};