leetcode 148. 排序链表 medium (重要)
题目描述:
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
解题思路:
方法1: 递归版归并排序 时间O(n log n) 空间O(logn)
主要就是在sortlist中将链表从中间断开,分成两部分,左右两边再分别调用排序的递归函数 sortList(),得到各自有序的链表后,再进行 merge(),这样整体就是有序的了。
方法2:自底向上归并排序
主要就是记住:
1.最后一段会比较特殊,假如最后一段size小于i,则不用排了(一定要有这个条件)
所以第二层循环是 for(int j=0;j+i<n;j += 2*i)
2. 因为右半边可能没有i个,所以right提前来到nullptr
所以归并每一段的循环条件是 while(num_left && num_right && right)
3.最后别忘了搞完了一段,要连接下一段
begin->next=right;
递归代码:
//递归归并
class Solution {
public:
ListNode* sortList(ListNode* head) {
if(!head || !head->next)
return head;
ListNode* slow=head,*fast=head;
while(fast->next && fast->next->next){
slow=slow->next;
fast=fast->next->next;
}
ListNode *right=slow->next;
slow->next=nullptr; // 断开这一步很关键
return merge(sortList(head),sortList(right));
}
ListNode* merge(ListNode* left, ListNode *right){
ListNode temp(-1);
ListNode *cur=&temp;
while(left && right){
if(left->val <= right->val){
cur->next=left;
cur=cur->next;
left=left->next;
} else{
cur->next=right;
cur=cur->next;
right=right->next;
}
}
if(left)
cur->next=left;
if(right)
cur->next=right;
return temp.next;
}
};
循环代码:
class Solution {
public:
ListNode* sortList(ListNode* head) {
if(!head || !head->next )
return head;
// 统计节点个数
int n=0;
for(ListNode *cur=head;cur;cur=cur->next)
++n;
ListNode dummy(-1);
dummy.next=head;
//每次排序的size是i
for(int i=1;i<n;i <<=1){
auto begin=&dummy;
//排序每一段,假如最后一段size小于i,则不用排了(一定要有这个条件)
for(int j=0;j+i<n;j += 2*i){
ListNode* left=begin->next, *right=left;
//让right指向这一段右半边的起点
for(int k=0;k<i;++k){
right=right->next;
}
//归并这一段
int num_left=i,num_right=i; //左半边待排个数,右半边待排个数
while(num_left && num_right && right){ //因为右半边可能没有i个,所以right提前来到nullptr
if(left->val <=right->val){
begin->next=left;
begin=begin->next;
left=left->next;
--num_left;
} else {
begin->next=right;
begin=begin->next;
right=right->next;
--num_right;
}
}
while(num_left){
begin->next=left;
begin=begin->next;
left=left->next;
--num_left;
}
while(num_right && right){
begin->next=right;
begin=begin->next;
right=right->next;
--num_right;
}
//连接下一段! 很重要!!!!
begin->next=right;
}
}
return dummy.next;
}
};

本文详细解析了LeetCode上第148题“排序链表”的解决方案,介绍了两种归并排序的方法:递归版和自底向上版。通过实例展示了如何在O(n log n)的时间复杂度和常数级空间复杂度下,对链表进行排序。

2226

被折叠的 条评论
为什么被折叠?



