Medium
题目描述
给你链表的头结点 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 * 10^4]内 -10^5 <= Node.val <= 10^5
进阶: 你可以在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?
解题思路
本题要求对链表进行排序,有多种解法:
方法一:归并排序(推荐) 采用分治思想,将链表分成两半,递归排序后再合并。关键步骤:
- 使用快慢指针找到链表中点,将链表分为两部分
- 递归地对两部分进行排序
- 合并两个有序链表
这种方法时间复杂度为 O(n log n),空间复杂度为 O(log n)(递归栈)。
方法二:自底向上归并排序 为了达到 O(1) 空间复杂度,可以使用自底向上的归并排序。从长度为1的子链表开始,逐步合并成长度为2、4、8…的有序链表,直到整个链表有序。
方法三:转换为数组排序 将链表节点值存储到数组中,排序后重建链表。虽然简单,但空间复杂度为 O(n)。
这里实现归并排序方法,它在时间和空间效率上都有很好的表现。
代码实现
class Solution {
public:
ListNode* sortList(ListNode* head) {
if (!head || !head->next) return head;
// 找到中点并分割链表
ListNode* mid = getMid(head);
ListNode* left = head;
ListNode* right = mid->next;
mid->next = nullptr;
// 递归排序
left = sortList(left);
right = sortList(right);
// 合并两个有序链表
return merge(left, right);
}
private:
ListNode* getMid(ListNode* head) {
ListNode* slow = head;
ListNode* fast = head->next;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
ListNode* merge(ListNode* l1, ListNode* l2) {
ListNode dummy(0);
ListNode* curr = &dummy;
while (l1 && l2) {
if (l1->val <= l2->val) {
curr->next = l1;
l1 = l1->next;
} else {
curr->next = l2;
l2 = l2->next;
}
curr = curr->next;
}
curr->next = l1 ? l1 : l2;
return dummy.next;
}
};
class Solution:
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if not head or not head.next:
return head
# 找到中点并分割链表
mid = self.getMid(head)
left = head
right = mid.next
mid.next = None
# 递归排序
left = self.sortList(left)
right = self.sortList(right)
# 合并两个有序链表
return self.merge(left, right)
def getMid(self, head):
slow = head
fast = head.next
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
def merge(self, l1, l2):
dummy = ListNode(0)
curr = dummy
while l1 and l2:
if l1.val <= l2.val:
curr.next = l1
l1 = l1.next
else:
curr.next = l2
l2 = l2.next
curr = curr.next
curr.next = l1 if l1 else l2
return dummy.next
public class Solution {
public ListNode SortList(ListNode head) {
if (head == null || head.next == null) return head;
// 找到中点并分割链表
ListNode mid = GetMid(head);
ListNode left = head;
ListNode right = mid.next;
mid.next = null;
// 递归排序
left = SortList(left);
right = SortList(right);
// 合并两个有序链表
return Merge(left, right);
}
private ListNode GetMid(ListNode head) {
ListNode slow = head;
ListNode fast = head.next;
while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
private ListNode Merge(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(0);
ListNode curr = dummy;
while (l1 != null && l2 != null) {
if (l1.val <= l2.val) {
curr.next = l1;
l1 = l1.next;
} else {
curr.next = l2;
l2 = l2.next;
}
curr = curr.next;
}
curr.next = l1 != null ? l1 : l2;
return dummy.next;
}
}
var sortList = function(head) {
if (!head || !head.next) return head;
// 找到中点并分割链表
const mid = getMid(head);
const left = head;
const right = mid.next;
mid.next = null;
// 递归排序
const sortedLeft = sortList(left);
const sortedRight = sortList(right);
// 合并两个有序链表
return merge(sortedLeft, sortedRight);
};
function getMid(head) {
let slow = head;
let fast = head.next;
while (fast && fast.next) {
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
function merge(l1, l2) {
const dummy = new ListNode(0);
let curr = dummy;
while (l1 && l2) {
if (l1.val <= l2.val) {
curr.next = l1;
l1 = l1.next;
} else {
curr.next = l2;
l2 = l2.next;
}
curr = curr.next;
}
curr.next = l1 || l2;
return dummy.next;
}
复杂度分析
| 复杂度类型 | 归并排序 | 自底向上归并 |
|---|---|---|
| 时间复杂度 | O(n log n) | O(n log n) |
| 空间复杂度 | O(log n) | O(1) |
相关题目
. Merge Two Sorted Lists (Easy)
. Sort Colors (Medium)
. Insertion Sort List (Medium)
. Sort Linked List Already Sorted Using Absolute Values (Medium)