题目:
因为时间复杂度要求(n*logn),所以考虑归并排序(但归并排序并不满足常数级的空间复杂度,还需要使用快慢指针?)。
参考链接:https://www.cnblogs.com/chengxiao/p/6194356.html
归并排序:
把一个待排序列从中间分两半,每半再各自应用归并排序处理。分出来的左右两半的归并操作中,同样也是先把每半序列再从中间劈开,分成两个子序列,再应用归并排序,以此类推,由此看是一个递归操作。
因此由此看来是,在每次归并函数调用中,先检测传进来的序列长度,如果序列中只有1个元素,则排不了序直接return返回。如果序列中的元素多于1个,则先把它从中间劈开,分出来的左右两个序列先各自调用归并排序,然后各自的归并排序完成之后,再把左右两个序列的所有元素合一起,来一个排序,这样排完,一次完整的归并函数的主要操作就完成了。
快慢指针参考:https://zhuanlan.zhihu.com/p/38521018
当我们直接在链表原地进行排序的时候,空间复杂的即为常数级。
用序列0、3、5、2、7、1、9、8测试
debug的时候,发现5、2这组从MergeSort()回传的时候,2给丢了,只有5。
原因是这句话:
MergeSort(A);
MergeSort(slow);
return Merge(A, slow);
如果里面的两个MergeSort()调用单独拿出来写成两句话的话,必须要有两个变量接着他们返回来的值,否则A和slow依然指着自己在调用MergeSort()前的两个原结构体,即是链表被排序了他俩也还指着原来两个结构体,之后再调用Merge(A, slow)的话这个调用逻辑就出错了。
所以要么写成这样:
A = MergeSort(A);
slow = MergeSort(slow);
return Merge(A, slow);
要么写成这样:
return Merge(MergeSort(A), MergeSort(slow));
源码:
#include <iostream>
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) {}
};
void dis_ListNode(ListNode *head)
{
for(ListNode *p = head; p; p = p->next)
{
std::cout << p->val << " ";
}
std::cout << std::endl;
}
class Solution
{
public:
ListNode* sortList(ListNode *A);
ListNode* Merge(ListNode *Left, ListNode *Right);
};
ListNode* Solution::sortList(ListNode *A)
{
if(!A || !(A->next))
{
return A;
}
ListNode *fast, *slow, *pre; // 先用快慢指针找到链表A的中间节点,把A劈两半,pre在while结束后最终指向左半部分的最后一个节点
pre = fast = slow = A;
while(fast && fast->next)
{
pre = slow;
slow = slow->next; // slow走一步
fast = fast->next->next; // fast走两步,这样两个指针遍历完slow刚好指向中间位置
}
pre->next = NULL;
return Merge(sortList(A), sortList(slow));
}
ListNode* Solution::Merge(ListNode *Left, ListNode *Right)
{
ListNode *head = nullptr;
if(Left->val < Right->val) // 确定head节点
{
head = Left;
Left = Left->next;
head->next = nullptr;
}
else
{
head = Right;
Right = Right->next;
head->next = nullptr;
}
ListNode *p = head; // 开始排序,Left和Right谁小就往后接
while(Left && Right)
{
if (Left->val < Right->val)
{
p->next = Left;
Left = Left->next;
p = p->next;
}
else
{
p->next = Right;
Right = Right->next;
p = p->next;
}
}
while(Left)
{
p->next = Left;
Left = Left->next;
p = p->next;
}
while(Right)
{
p->next = Right;
Right = Right->next;
p = p->next;
}
p->next = nullptr;
dis_ListNode(head);
return head;
}
int main()
{
int i = 3; // 创建待排链表
int val[] = {4, 2, 1, 3};
ListNode *p = new ListNode(val[i--], nullptr);
for ( ; i >= 0; --i)
{
ListNode *q = new ListNode(val[i], p);
p = q;
}
ListNode *head = p;
std::cout << "待排链表中的元素:";
dis_ListNode(head);
// 归并排序
Solution *solution = new Solution;
head = solution->sortList(head);
std::cout << "排序后的序列:";
dis_ListNode(head);
return 0;
}