148. 排序链表
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
示例:
输入:head = [4,2,1,3]
输出:[1,2,3,4]
一、暴力解法
Colletions的2个静态排序方法:
排序:sort(list) sort(list,comparator)
最大最小值:max(list) min(list)
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
ListNode cur=head;
List<Integer> list=new ArrayList<>();
while(cur!=null)
{
list.add(cur.val);
cur=cur.next;
}
Collections.sort(list);
cur=head;
for(Integer x:list)
{
cur.val=x;
cur=cur.next;
}
return head;
}
}
进阶:
你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?
方法一 归并排序:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
return head==null?null:mergeSort(head);//空指针判断
}
public ListNode mergeSort(ListNode head)
{
if(head.next==null)//防止单个指针
{
return head;
}
//快慢指针
ListNode fast=head;//快慢指针,并且标记一个慢指针
ListNode slow=head;
ListNode prev=slow;
while(fast!=null && fast.next!=null)
{
prev=slow;
fast=fast.next.next;
slow=slow.next;
}
prev.next=null;//一分为二
ListNode left=mergeSort(head);
ListNode right=mergeSort(slow);
return merge(left,right);
}
ListNode merge(ListNode l,ListNode r)//这个其实就是我们之前的合并两个有序链表,虽然他是无序的,道理都是一样的,不懂的可以看我的这个博客:https://blog.csdn.net/qq_42956868/article/details/122199463?spm=1001.2014.3001.5501
{
ListNode dummyHead=new ListNode(0);
ListNode cur=dummyHead;
while(l!=null && r!=null)
{
if(l.val<=r.val){
cur.next=l;
cur=cur.next;
l=l.next;
}
else{
cur.next=r;
cur=cur.next;
r=r.next;
}
}
if(l!=null)
{
cur.next=l;
}
if(r!=null)
{
cur.next=r;
}
return dummyHead.next;
}
}
方法二:快速排序
快速排序的实质:
1.选定Pivot中心轴
2.将大于Pivot的数字放在Pivot的右边
3.将小于Pivot的数字放在Pivot的左边
4.分别对左右子序列重复前三步操作
所以在编写代码之前我也忘记快排的定义,然后B站看看视频了解了下概念,下面是编写的代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode sortList(ListNode head) {
if(head==null || head.next==null) return head;//这里是单数据或者空数据的时候,直接返回数据
ListNode dummyHead=new ListNode();//定义虚拟指针
dummyHead.next=head;//连接头结点
return quickSort(dummyHead,null);//使用快排
}
public ListNode quickSort(ListNode head,ListNode end)
{
if(head==end || head.next==end || head.next.next==end){
return head;
}//快排判断如果虚拟头结点以及连接头结点或者单目标情况,直接返回数据
ListNode temp=new ListNode();//临时虚拟变量
ListNode partition=head.next;//分割线,重点
ListNode position=partition;//位置指针
ListNode tmp=temp;//临时虚拟变量的指针
while(position.next!=end)//判断位置指针是否已经跳过末尾元素
{
if(position.next.val<partition.val)//临时虚拟变量指针存储小与分割线的数据
{
tmp.next=position.next;
tmp=tmp.next;
position.next=position.next.next;
}else{
position=position.next;
}
}
tmp.next=head.next;//连接较大的数据
head.next=temp.next;//头结点更新
quickSort(head,partition);//左边快排
quickSort(partition,end);//右边快排
return head.next;
}
}