题目
Sort a linked list in O(n log n) time using constant space complexity.
思路
因为题目要求复杂度为O(nlogn),故可以考虑归并排序的思想。
归并排序的一般步骤为:
1)将待排序数组(链表)取中点并一分为二;
2)递归地对左半部分进行归并排序;
3)递归地对右半部分进行归并排序;
4)将两个半部分进行合并(merge),得到结果。
所以对应此题目,可以划分为三个小问题:
1)找到链表中点 (快慢指针思路,快指针一次走两步,慢指针一次走一步,快指针在链表末尾时,慢指针恰好在链表中点);
2)写出merge函数,即如何合并链表。
3)写出mergesort函数,实现上述步骤。
代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *sortList(ListNode *head) {
if(!head || !head->next)
return head;
ListNode* fast=head->next,*slow=head;
while(fast && fast->next){
fast=fast->next->next;
slow=slow->next;
}
ListNode *right=sortList(slow->next);
slow->next=nullptr;
ListNode *left=sortList(head);
return merge(left,right);
}
ListNode* merge(ListNode *left,ListNode *right){
if(!left)
return right;
if(!right)
return left;
ListNode *tmp=new ListNode(0),*head=tmp;
while(left && right){
if(left->val<right->val){
tmp->next=left;
left=left->next;
}
else{
tmp->next=right;
right=right->next;
}
tmp=tmp->next;
}
if(left)
tmp->next=left;
if(right)
tmp->next=right;
return head->next;
}
};
细节
- merge函数里面初始化节点tmp要用new,不可以用ListNode *tmp=nullptr(有大佬能帮忙解释原因吗?)
- merge函数因为tmp一直在移动直到为空,所以要在一开始就用一个head指向tmp的头节点,方能return出正确的合并链表
- C/C++ &与&& |与|| 的区别:&&是逻辑与,||是逻辑或,&是按位与,|是按位或
- 归并排序时间复杂度平均情况、最坏情况、最好情况都是O(nlogn),空间复杂度O(n),是一个稳定的排序算法,易于在链表上实现。
本文详细介绍了如何使用归并排序算法对链表进行排序,包括找到链表中点、合并链表的merge函数以及实现mergesort函数的步骤。特别提到在merge函数中初始化节点tmp需要注意的问题,并探讨了C/C++中逻辑与&&和按位与&的区别。该排序算法具有O(nlogn)的时间复杂度和O(n)的空间复杂度。
583

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



