方法一:归并排序
1、利用归并排序将链表分而治之,不断地将链表从中间结点拆解为两个链表;
2、拆解至单个结点后进行排序,将问题转化为两个排序好的链表融合为一个链表的问题;自下而上递归将两个链表进行融合,最终得到排序后的链表。
利用快慢指针得到链表的中间结点
时间复杂度:o(nlog2n),每级划分最坏需要遍历链表全部元素,因此为o(n),每级合并都是将同级的子问题链表遍历合并,因此也为o(n),分治划分为二叉树型,一共有o(log2n)层,因此复杂度为o((n+n)∗log2n)=o(nlog2n)。
空间复杂度:o(log2n),递归栈的深度最坏为树型递归的深度,log2n层。
class Solution { public: ListNode* merge(ListNode* phead1, ListNode* phead2) { if(phead1 == nullptr) return phead2; if(phead2 == nullptr) return phead1; ListNode* res = new ListNode(0); ListNode* newhead = res; while (phead1 && phead2) { if(phead1->val < phead2->val) { newhead->next = phead1; phead1 = phead1->next; } else { newhead->next = phead2; phead2 = phead2->next; } newhead = newhead->next; } if(phead1) newhead->next = phead1; if(phead2) newhead->next = phead2; return res->next; } ListNode* sortInList(ListNode* head) { //特殊情况处理 if(head == nullptr || head->next == nullptr) return head; //利用快慢指针得到链表的中间结点,将链表表从中点处拆分为两个链表 ListNode* left = head; ListNode* middle = head->next; ListNode* right = head->next->next; while (right != nullptr && right->next != nullptr) { left = left->next; middle = middle->next; right = right->next->next; } //将左边链表拆分成独立的链表 left->next = nullptr; //递归融合得到排序后的链表 return merge(sortInList(head), sortInList(middle)); } };
方法二:将链表转换为数组排序求解
1、将链表转换为数组;
2、数组排序
3、将排序后的数组转换为链表。
时间复杂度:o(nlog2n),sort函数一般为优化后的快速排序,复杂度为o(nlog2n)
空间复杂度:o(n)
class Solution { public: ListNode* sortInList(ListNode* head) { //特殊情况处理 if (head == nullptr || head->next == nullptr) return head; //链表转换为数组 vector<int> vet; while (head) { vet.push_back(head->val); head = head->next; } //数组排序 sort(vet.begin(), vet.end()); ListNode* res = new ListNode(0); ListNode* newhead = res; //排序后的数组转换为链表 for (int i = 0; i < vet.size(); i++) { newhead->next = new ListNode(vet[i]); newhead = newhead->next; } newhead->next = nullptr; return res->next; } };