Files
LeetCode/链表/12. 排序链表.md
T
2025-10-04 12:43:05 +08:00

104 lines
2.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 排序链表
## 题目
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
示例 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
进阶:你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?
## 思路
- 归并排序
- 拆分
- 快慢指针
- 合并
## 代码
```java
/**
* 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) {
// -- Divide -> Sort -> Merge --
// Special
if (head == null || head.next == null) {
return head;
}
// Init: slow, fast, dummyHead
ListNode dummyHead = new ListNode(-1);
dummyHead.next = head;
ListNode slow = dummyHead;
ListNode fast = dummyHead;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
// Divide: [headA .... tailA(slow)] [headB(slow.next) ... tailB]
ListNode headA = head;
ListNode headB = slow.next;
slow.next = null;
// Sort
headA = sortList(headA);
headB = sortList(headB);
// Merge
return mergeList(headA, headB);
}
public ListNode mergeList(ListNode headA, ListNode headB) {
// Init: dummyHead, tail
ListNode dummyHead = new ListNode(-1);
ListNode tail = dummyHead;
// Traverse: Merge
while (headA != null && headB != null) {
int valA = headA.val;
int valB = headB.val;
if (valA < valB) {
tail.next = headA;
headA = headA.next;
} else {
tail.next = headB;
headB = headB.next;
}
tail = tail.next;
}
// Operation: After
tail.next = headA == null ? headB : headA;
return dummyHead.next;
}
}
```