问题描述
给定一个无序单链表,实现单链表的排序(按升序排序)。
示例
示例1
输入
[1,3,2,4,5]
输出
{1,2,3,4,5}
解决思路
思路
- 归并排序
(1)找到链表的中点,以中点为分界,将链表拆分成两个子链表。【寻找链表的中点可以使用快慢指针的做法,快指针每次移动 2 步,慢指针每次移动 1 步,当快指针到达链表末尾时,慢指针指向的链表节点即为链表的中点】
(2)对两个子链表分别排序。
(3)将两个排序后的子链表合并,得到完整的排序后的链表。【相当于合并两个有序的链表】
代码实现
// 思路1:归并排序
public class Solution {
public ListNode sortList(ListNode head) {
return sortList(head, null);
}
// 通过递归的方式二分链表
public ListNode sortList(ListNode head, ListNode tail) {
if (head == null) {
return head;
}
// 当head和tail只有一个节点的时候,不需要继续拆分
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 = sortList(head, mid);
ListNode list2 = sortList(mid, tail);
// 合并链表
ListNode sorted = merge(list1, list2);
return sorted;
}
public ListNode merge(ListNode head1, ListNode head2) {
ListNode dummyHead = new ListNode(0);
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(NlogN):N为链表的长度,logN是二分拆分链表
空间复杂度分析:
O(logN):空间复杂度取决于递归调用的栈空间
小伙伴如果想测试的话,可以直接到牛客网这个链接做测试