leetcode:148. 排序链表
题目
给你链表的头结点 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 = []
输出:[]
解答 & 代码
解法一:自顶向下归并排序(递归)
- 定位到链表中间节点 mid,将链表拆分成左、右两个子链表
- 分别递归排序左子链表、右子链表
将排序后的左、右子链表合并
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
private:
// 寻找链表中间节点并返回
ListNode* findMidNode(ListNode* head)
{
// 注意这里快、慢指针都从虚拟头节点开始遍历,这样偶数节点链表定位到中间节点,奇数节点
// 链表则定位到第一个中间节点,这样得到的中间节点就可以作为左子节点的最后一个节点。
// 而如果从 head 开始遍历,奇数节点链表会定位到第二个中间节点,就只能得到右子链表的起点
ListNode* dummyHead = new ListNode(0, head);
ListNode* fast = dummyHead;
ListNode* slow = dummyHead;
while(fast != nullptr && fast->next != nullptr)
{
fast = fast->next->next;
slow = slow->next;
}
return slow;
}
// 合并两个有序链表
ListNode* mergeList(ListNode* head1, ListNode* head2)
{
ListNode* dummyHead = new ListNode();
ListNode* pre = dummyHead;
ListNode* cur1 = head1;
ListNode* cur2 = head2;
while(cur1 != nullptr && cur2 != nullptr)
{
if(cur1->val < cur2->val)
{
pre->next = cur1;
pre = cur1;
cur1 = cur1->next;
}
else
{
pre->next = cur2;
pre = cur2;
cur2 = cur2->next;
}
}
if(cur1 != nullptr)
pre->next = cur1;
if(cur2 != nullptr)
pre->next = cur2;
return dummyHead->next;
}
public:
// 递归归并排序
ListNode* sortList(ListNode* head) {
// 递归结束条件:链表为空 or 只有一个节点
if(head == nullptr || head->next == nullptr)
return head;
// 1. 定位到链表中间节点 mid,将链表拆分成左、右两个子链表
ListNode* mid = findMidNode(head);
ListNode* rightHead = mid->next; // 右子链表的头节点
mid->next = nullptr; // 将左子链表的尾部指向 nullptr
// 2. 分别递归排序左子链表、右子链表
head = sortList(head);
rightHead = sortList(rightHead);
// 3. 将排序后的左、右子链表合并
head = mergeList(head, rightHead);
return head;
}
};
复杂度分析:设链表长为 N
- 时间复杂度 O(N logN):归并排序时间复杂度
- 空间复杂度 O(log N):递归栈空间复杂度
执行结果:
执行结果:通过
执行用时:132 ms, 在所有 C++ 提交中击败了 12.01% 的用户
内存消耗:59.3 MB, 在所有 C++ 提交中击败了 5.02% 的用户
解法二:自底向上归并排序
[中等] 148. 排序链表
复杂度分析:设链表长为 N
- 时间复杂度 O(N logN):
- 空间复杂度 O(1):