148. 排序链表
148. 排序链表
给你链表的头结点
head
,请将其按升序排列并返回排序后的列表示例1: 4 --> 2 --> 1 --> 3
1 --> 2 --> 3 --> 4输入:head = [4,2,1,3]
输出:[1,2,3,4]提示:
- 链表中节点的数目在范围
[0, 5 * 10^4]
内-10^5 <= Node.val <= 10^5
进阶:你可以在
O(n log n)
时间复杂度和常数级空间复杂度下,对链表进行排序吗?
java:
class Solution {
public ListNode sortList(ListNode head) {
return toSortList(head, null);
}
// 递归,然后对列表进行分割
public ListNode toSortList(ListNode head, ListNode tail) {
// 判断条件,如果为空 直接就返回
if (head == null) {
return head;
}
if (head.next == tail) {
head.next = null;
return head;
}
// 使用快慢指针法,找到分割点,进行切割
ListNode slow = head, fast = head;
while (fast != tail) {
slow = slow.next;
fast = fast.next;
if (fast != tail) {
fast = fast.next;
}
}
// 慢指针就是分割点
ListNode mid = slow;
// 分割了一次之后,在继续进行分割
// 分割中间点以前的链表元素
ListNode list1 = toSortList(head, mid);
// 分割中间点以后的链表元素
ListNode list2 = toSortList(mid, tail);
// 对分割好的链表,进行排序,最后就可以返回结果
ListNode sorted = merge(list1, list2);
return sorted;
}
/**
排序算法,定义一条新的链表,对前面两个进行排序 大的在后面,小的在前面
*/
public ListNode merge(ListNode head1, ListNode head2) {
ListNode dummyHead = new ListNode(0);
// temp1 temp2 两个临时指针
ListNode temp = dummyHead, temp1 = head1, temp2 = head2;
while (temp1 != null && temp2 != null) {
if (temp1.val <= temp2.val) {
temp.next = temp1;
temp1 = temp1.next;
} else {
temp.next = temp2;
temp2 = temp2.next;
}
temp = temp.next;
}
if (temp1 != null) {
temp.next = temp1;
} else if (temp2 != null) {
temp.next = temp2;
}
// 返回结果
return dummyHead.next;
}
}
解析:
改题目解法比较复杂,主要难点在于给出的进阶操作,时间复杂度为O(n log n)
,因此使用了归并排序
归并排序:时间复杂度O(n log n)
,分的时间复杂度O(log n)
,合并的过程的复杂度是O(n)
先把链表切开,然后再进行合并的操作
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)