给你链表的头结点 head
,请将其按 升序 排列并返回 排序后的链表 。
示例 1:
输入:head = [4,2,1,3] 输出:[1,2,3,4]
示例 2:
输入:head = [-1,5,3,4,0] 输出:[-1,0,3,4,5]
示例 3:
输入:head = [] 输出:[]
分析:
方法一:将链表的所有元素存放在数组中进行排序,再将排好序的数值依次放到链表里。
//方法一
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
int cmp(const void *a,const void *b)
{
int *aa=(int*)a;
int *bb=(int*)b;
return *aa-*bb;
}
struct ListNode* sortList(struct ListNode* head) {
if(head==NULL)return NULL;
struct ListNode *p=head;
int num[50010]={0},t=0;
while(p!=NULL)
num[t++]=p->val,p=p->next;
qsort(num,t,sizeof(int),cmp);
p=head;
int l=0;
while(p!=NULL)
p->val=num[l++],p=p->next;
return head;
}
方法二:快速排序。
找到链表中的最大值和最小值,以它们的平均数mid作为分界值,小于等于mid的放到链表h1,大于mid的放到链表h2,之后再把h2挂在h1的后面即可。
//方法二 快速排序
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* sortList(struct ListNode* head) {
if(head==NULL)return NULL;
if(head->next==NULL)return head;
struct ListNode *prehead=(struct ListNode*)malloc(sizeof(struct ListNode));
prehead->next=head;
struct ListNode *h1=(struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode *h2=(struct ListNode*)malloc(sizeof(struct ListNode));
h1->next=h2->next=NULL;
int l=head->val,r=head->val;
while(head->next!=NULL)
{
head=head->next;l=fmin(l,head->val);r=fmax(r,head->val);
}
if(l==r)
{
struct ListNode *p=prehead->next;
free(prehead);
free(h1);
free(h2);
return p;
}
int mid=(l+r)>>1;
head=prehead->next;
struct ListNode *p=head;
while(head!=NULL)
{
p=head;
head=head->next;
if(p->val<=mid)p->next=h1->next,h1->next=p;
else p->next=h2->next,h2->next=p;
}
h1->next=sortList(h1->next);
h2->next=sortList(h2->next);
p=h1;
while(p->next!=NULL)p=p->next;
p->next=h2->next;
struct ListNode *ans=h1->next;
free(prehead);
free(h1);
free(h2);
return ans;
}
方法三:自顶向下归并排序。
- 找到链表的中点,以中点为分界,将链表拆分成两个子链表。寻找链表的中点可以使用快慢指针的做法,快指针每次移动 2 步,慢指针每次移动 1 步,当快指针到达链表末尾时,慢指针指向的链表节点即为链表的中点。
- 对两个子链表分别排序。
- 将两个排序后的子链表合并,得到完整的排序后的链表。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* sortList(struct ListNode* head) {
if(head==NULL)return NULL;
if(head->next==NULL)return head;
struct ListNode *prehead=(struct ListNode*)malloc(sizeof(struct ListNode));
prehead->next=head;
struct ListNode *fast,*low;
fast=low=prehead;
while(fast->next!=NULL)
{
low=low->next;
fast=fast->next;
if(fast->next!=NULL)fast=fast->next;
}
if(fast==low)
{
free(prehead);
return fast;
}
struct ListNode *h1=(struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode *h2=(struct ListNode*)malloc(sizeof(struct ListNode));
h1->next=head;h2->next=low->next;low->next=NULL;
h1->next=sortList(head);
h2->next=sortList(h2->next);
struct ListNode *h=(struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode *p,*q,*r;
p=h1->next,q=h2->next,r=h;
while(p!=NULL||q!=NULL)
{
if(p==NULL&&q!=NULL)r->next=q,q=q->next;
else if(p!=NULL&&q==NULL)r->next=p,p=p->next;
else if(p->val<q->val)r->next=p,p=p->next;
else r->next=q,q=q->next;
r=r->next;
}
//r->next=NULL;
p=h->next;
free(h1);
free(h2);
free(h);
return p;
}
方法四:自底向上归并排序
具体做法如下。
- 用 subLength 表示每次需要排序的子链表的长度,初始时 subLength=1。
- 每次将链表拆分成若干个长度为 subLength 的子链表(最后一个子链表的长度可以小于 subLength),按照每两个子链表一组进行合并,合并后即可得到若干个长度为 subLength×2 的有序子链表(最后一个子链表的长度可以小于 subLength×2)。
- 将 subLength 的值加倍,重复第 2 步,对更长的有序子链表进行合并操作,直到有序子链表的长度大于或等于 length,整个链表排序完毕。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
//方法四 这里我把调试的部分也留下了
struct ListNode* sortList(struct ListNode* head) {
if(head==NULL)return NULL;
if(head->next==NULL)return head;
struct ListNode *prehead=(struct ListNode*)malloc(sizeof(struct ListNode));
prehead->next=head;
int l=0,t=0;
struct ListNode *p=head,*q=prehead;
while(p!=NULL)l++,p=p->next;
p=prehead->next;
for(int i=1;i<l;i=fmin(i*2,l))
{
p=prehead->next;t=0;
struct ListNode *index;
while(p!=NULL)
{
int l1=0,l2=0;
struct ListNode *p1,*q1,*p2,*q2;
p1=p;
while(p!=NULL&&l1<i)l1++,q1=p,p=p->next;
q1->next=NULL;
if(p==NULL)break;
p2=p;
while(p!=NULL&&l2<i)l2++,q2=p,p=p->next;
q2->next=NULL;
/*
printf("i=%d l=%d\n",i,l);
struct ListNode *test=p1;
printf("p1=");
while(test!=NULL)printf("%d ",test->val),test=test->next;
printf("\n");
test=p2;
printf("p2=",i);
while(test!=NULL)printf("%d ",test->val),test=test->next;
printf("\n");
*/
struct ListNode *h=(struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode *r=h;
while(p1!=NULL||p2!=NULL)
{
if(p1==NULL&&p2!=NULL)r->next=p2,p2=p2->next;
else if(p1!=NULL&&p2==NULL)r->next=p1,p1=p1->next;
else if(p1->val<p2->val)r->next=p1,p1=p1->next;
else r->next=p2,p2=p2->next;
r=r->next;
}
if(t==0)prehead->next=h->next,t++,index=r;
else index->next=h->next,index=r;;
r->next=p;
/*
test=h->next;
printf("test=");
while(test!=NULL)printf("%d ",test->val),test=test->next;
printf("\n");
*/
free(h);
/*
printf("r=%d\n",r->val);
test=p;
printf("p=",i);
while(test!=NULL)printf("%d ",test->val),test=test->next;
printf("\n");
test=prehead->next;
printf("prehead=",i);
while(test!=NULL)printf("%d ",test->val),test=test->next;
printf("\n");
*/
}
}
q=prehead->next;
free(prehead);
return q;
}
方法三、方法四来源:
作者:力扣官方题解
链接:https://leetcode.cn/problems/sort-list/solutions/492301/pai-xu-lian-biao-by-leetcode-solution/