一、题目介绍
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、解题思路
利用归并排序完成该题目,因为是对链表排序,所以不需要引入太多的额外空间。归并排序分为以下三步:
(1)计算链表长度
(2)自底向上分割链表,先按照长度为2^0分割,再按照2^1分割,再按照2^2分割,以此类推……
(3)每次分割之后,需要将分割后的链表,有序合并。
三、解题代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* cut(ListNode* node, int n) //以node为起点切掉n个节点,返回剩下链表的表头
{
ListNode* p = node;
while(--n && p)
{
p = p->next;
}
if(p == NULL)
return NULL;
ListNode* next = p->next;
p->next = NULL;
return next;
}
ListNode* merge(ListNode* l, ListNode* r)
{
ListNode* node = new ListNode(0);
ListNode* p = node;
while(l && r)
{
if(l->val < r->val)
{
p->next = l;
l = l->next;
}
else
{
p->next = r;
r = r->next;
}
p = p->next;
}
p->next = l == NULL ? r: l;
return node->next;
}
ListNode* sortList(ListNode* head) {
ListNode* newHead = new ListNode(0);
newHead->next = head;
ListNode* pTemp = head;
//计算链表长度
int len = 0;
while(pTemp)
{
len++;
pTemp = pTemp->next;
}
//归并排序
for(int i = 1; i < len; i *= 2)
{
ListNode* tail = newHead;
ListNode* cur = newHead->next;
//首先按照长度为1切分链表,再合并;再按照长度为2^1切分链表,再合并,依次类推……
while(cur)
{
ListNode* left = cur; //left->@->@->null 左链表
ListNode* right = cut(left, i); //右链表 right->@->@->null
cur = cut(right, i); // cur->@->@->null
tail->next = merge(left, right); //合并两个链表
while(tail->next)
tail = tail->next;
}
}
return newHead->next;
}
};