LeetCode 148. 排序链表
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
进阶:
- 你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?
示例1:
输入:head = [4,2,1,3]
输出:[1,2,3,4]
示例 2:
输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]
示例3:
输入:head = []
输出:[]
提示:
- 链表中节点的数目在范围
[0, 5 * 104]
内 -105 <= Node.val <= 105
归并排序
自顶向下归并排序(递归)
class Solution {
public ListNode sortList(ListNode head) {
/* * * * * * * * * * * *
* 使用递归的归并排序 *
* * * * * * * * * * * */
if (head == null || head.next == null) return head;
// 寻找中点,节点为奇数个时为中点,节点为偶数个时为左侧中间点
ListNode fast = head.next, slow = head;
while (fast != null && fast.next != null) {
fast = fast.next.next;
slow = slow.next;
}
ListNode temp = slow.next;
slow.next = null;
// 归并
ListNode left = sortList(head);
ListNode right = sortList(temp);
ListNode result = merge(left, right);
return result;
}
// 按升序合并两个链表(LC 21.合并两个有序链表)
private ListNode merge(ListNode left, ListNode right) {
ListNode dummyNode = new ListNode(0);
ListNode l = left, r = right, temp = dummyNode;
while (l != null && r != null) {
if (l.val <= r.val) {
temp.next = l;
l = l.next;
} else {
temp.next = r;
r = r.next;
}
temp = temp.next;
}
if (l != null) {
temp.next = l;
} else if (r != null) {
temp.next = r;
}
return dummyNode.next;
}
}
/**
* 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; }
* }
*/
- 时间复杂度:O(nlogn)
- 空间复杂度:O(logn),递归调用的栈空间。
自底向上归并排序(非递归)
- 遍历链表,计算总长度length,用 subLength 表示每次需要排序的子链表的长度,初始时 subLength=1。
- 每次将链表拆分成若干个长度为 subLength 的子链表(最后一个子链表的长度可以小于 subLength),按照每两个子链表一组进行合并,合并后即可得到若干个长度为 subLength×2 的有序子链表(最后一个子链表的长度可以小于 subLength×2)。
- 将 subLength 的值加倍,重复第 2 步,对更长的有序子链表进行合并操作,直到有序子链表的长度大于或等于 length,整个链表排序完毕。
class Solution {
public ListNode sortList(ListNode head) {
/* * * * * * * * * * * *
* 不使用递归的归并排序 *
* * * * * * * * * * * */
if (head == null || head.next == null) return head;
int length = 0;
ListNode node = head;
// 统计链表长度
while (node != null) {
length++;
node = node.next;
}
ListNode dummyNode = new ListNode(0, head);
for (int subLength = 1; subLength < length; subLength *= 2) {
ListNode prev = dummyNode, curr = dummyNode.next;
while (curr != null) {
ListNode left = curr;
for (int i = 1; i < subLength && curr.next != null; i++) {
curr = curr.next;
}
ListNode right = curr.next;
curr.next = null;
curr = right;
for (int i = 1; i < subLength && curr != null && curr.next != null; i++) {
curr = curr.next;
}
ListNode next = null;
if (curr != null) {
next = curr.next;
curr.next = null;
}
ListNode merged = merge(left, right);
prev.next = merged;
while (prev.next != null) {
prev = prev.next;
}
curr = next;
}
}
return dummyNode.next;
}
}
- 时间复杂度:O(nlogn)
- 空间复杂度:O(1)