题目链接:
题目大意:
给一个无序链表排序,要求时间复杂度O(n log n),空间复杂度O(1)。
分析:
最开始看到空间复杂度为常数,第一反应是堆排序。然而并不行,堆排序是基于数组的吧,然后是快排,但是快排掌握的并不好,而且想了一下归并排序如果是用链表的话,其实是可以避免空间复杂度为O(n)的情况的。
里面还涉及一个小算法吧,就是找链表的中点,可以用两个指针,low与high,一个步长为1一个步长为2,当high->next为空或high->next->next为空时,此时low在中点位置。
最近在学数据结构,刚刚学完排序,练下排序的题,顺便加深对链表的影响。主要是有个师兄说我学数据结构就是在背代码,根本不会灵活运用……QAQ好伤感,我自己觉得不是这样的啊,但是既然有人这样说了,我还是多练练LeetCode上的题吧。嗯,这道题确实是道好题,加深了我对链表和归并排序的理解,诶~~~指针指来指去还是有点晕,第一次写MSort函数的时候,传参传的不是指针的引用,链表老是丢结点。关于指针还是要多思考,在脑袋里多指过去指过来几次,慢慢就不晕了。
代码:
class Solution {
public:
void Merge_Sort(ListNode* &L,ListNode* R){
ListNode* pHead = (ListNode*)malloc(sizeof(ListNode));
pHead->next = L;
ListNode* ptrL = L;
ListNode* ptrR = R;
ListNode* pre = pHead;
while (ptrL!=NULL&& ptrR!=NULL)
{
if (ptrL->val <= ptrR->val)
{
pre = ptrL;
ptrL = ptrL->next;
}
else
{
ListNode* tmp = ptrR->next;
pre->next = ptrR;
ptrR->next = ptrL;
ptrR = tmp;
pre = pre->next;
}
}
if (ptrR!= NULL)
{
pre->next = ptrR;
}
L = pHead->next;
}
void MSort(ListNode* &List){
if (List == NULL || List->next==NULL)
{
return;
}
ListNode* low=List;
ListNode* high=List;
ListNode* pre = NULL;
ListNode* newList = NULL;
while (high->next != NULL && high->next->next!=NULL)
{
pre = low;
low = low->next;
high = high->next->next;
}
newList = low->next;
low->next = NULL;
MSort(List);
MSort(newList);
Merge_Sort(List,newList);
}
ListNode* sortList(ListNode* head) {
MSort(head);
return head;
}
};