题目描述
给你链表的头结点头,请将其按升序排列并返回排序后的链表。进阶:
你可以在O(n对数n)时间复杂度和常数级空间复杂度下,对链表进行排序吗?
写在前面
本文答案参考(Ctrl CV)自LeetCode网友题解。
解法1:归并排序
(运用快慢指针)将链表分成两半,对左半边和右半边进行排序后,再将这两半连起来。此解法有O(n对数n)时间复杂度和常数级空间复杂度
递归比较好写,迭代的话需要将链表依次一个一组、2个一组、4个一组、8个一组地分组。
代码:递归
级解决方案{公共列表节点排序列表(列表节点头){ 0
if (head==null || head.next==null)
返回头;
列表节点快=头。下一个,慢=头
趁着(快!=null fast.next!=null){ 0
慢=慢。下一步;
快=快。下一个。接下来;
}
ListNode tmp=慢. next
slow.next=null
ListNode left=排序列表(head);
列表节点右=排序列表(tmp);
列表节点h=新的ListNode(0);
ListNode RES=h;
而(左!=空右!=null){ 0
如果(左。英国压力单位右。val){ 0
h.next=左侧;
左=左。下一个
} else {
h.next=右;
右=右。下一个
}
h=h . next
}
h.next=左侧!=null?左:右;
返回res.next
}
}
作者:jyd
链接:https://leet代码-cn。com/problems/sort-list/solution/sort-list-GUI-bing-pai-Xu-Lian-Pio-by-jyd/
来源:力扣(LeetCode)
代码:迭代
类解决方案{公共列表节点排序列表(列表节点头){ 0
int length=GetLength(head);
ListNode dummy=new ListNode(-1);
dummy.next=head
for(int step=1;步长;step*=2){ //依次将链表分成一块,2块,4块.
//每次变换步长,预指针和坏蛋指针都初始化在链表头
列表节点pre=虚拟
ListNode cur=dummy.next
while(cur!=null){ 0
ListNode h1=cur//第一部分头(第二次循环之后弯曲的为剩余部分头,不断往后把链表按照步长步骤分成一块一块.)
ListNode h2=split(h1,step);//第二部分头
cur=split(h2,step);//剩余部分的头
ListNode temp=merge(h1,H2);//将一二部分排序合并
pre.next=temp//将前面的部分与排序好的部分连接
while(pre.next!=null){ 0
pre.next//之前把在…之前指针移动到排序好的部分的末尾
}
}
}
返回笨蛋,下一个
}
public int GetLength(列表节点头){ 0
//获取链表长度
int count=0;
趁着(头!=null){ 0
计数;
head=head.next
}
返回计数;
}
公共列表节点拆分(列表节点头,int步骤){ 0
//断链操作返回第二部分链表头
if(head==null)返回null
列表节点cur=head
for(int I=1;istep cur.next!=NulL){ 0
cur=cur.next
}
ListNode right=cur.next
cur.next=null//切断连接
返回右侧;
}
公共列表节点合并(列表节点h1,列表节点H2){ 0
//合并两个有序链表
ListNode head=new ListNode(-1);
ListNode p=head
while(h1!=空h2!=null){ 0
if(h1。瓦尔H2。val){ 0
p.next=h1
h1=h1.next
}
else{
p.next=h2
h2=h2.next
}
p=p . next
}
if(h1!=null)p . next=h1;
if(h2!=null)p . next=H2;
返回下一个
}
}
作者:樱桃-n1
链接:https://leet代码-cn。com/问题/排序列表/解决方案/pai-Xu-Lian-飚-迪-桂-迪-代-香-洁-依-彻/
来源:力扣(LeetCode)