题目
要求对链表O(nlogn)排序,并只能用常数空间。
思路
这道题是1A的,一看这题就是要考链表实现归并排序。
归并排序,整体思路(merge_sort)
1、找出链表中点,将链表分成两个子链表,这里将用快慢指针的技巧
2、对两个链表递归进行归并排序,返回链表头指针(mergelist)
3、根据返回的头指针,合并两个链表,递归返回拼接后的头指针
测试边界
链表为空,或者链表只有一个元素
代码
class Solution{
public :
ListNode *sortList(ListNode * head)
{
return merge_sort(head);
}
ListNode *merge_sort(ListNode *head)
{
if (head==NULL || head->next==NULL) return head;//only just one item
ListNode *p=head,*q=head,*pre=head;
while(q !=NULL && q->next!=NULL) //split method is very comprehensive.q is twice speed than p.
{
pre = p;
p=p->next;
q=q->next->next;
}
//p is the middle of list
pre->next = NULL;
ListNode *s1=merge_sort(head);
ListNode *s2=merge_sort(p);
ListNode *s3=merge_list(s1,s2);
return s3;
}
ListNode *merge_list(ListNode * s1,ListNode* s2)
{
ListNode *p ,*h1;
if(s1==NULL) return s2;
if (s2==NULL) return s1;
if (s1->val<s2->val) {p= s1; s1 = s1->next;}
else {p=s2;s2=s2->next;}//确定s1,s2中小者作为头指针
h1 = p;//保存合并链表头
while(s1!=NULL && s2!=NULL)//顺序遍历进行,合并
{
if (s1->val < s2->val){
p->next = s1;
s1 = s1->next;
p = p->next;
}
else{
p->next = s2;
s2 = s2->next;
p=p->next;
}
}
if (s1==NULL) p->next = s2;//合并剩余元素
else p->next = s1;
return h1 ;
}
ListNode *input()
{
int x;
ListNode *p,*head,*q;
cin>>x;
head = new ListNode(x);
q=head;
for (int i=1;i<1;i++)
{
cin>>x;
p=new ListNode(x);
q->next = p;
q=q->next;
}
return head;
}
void output(ListNode *h)
{
while(h!=NULL){
cout<<h->val<<endl;
h = h->next;
}
}
};