在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3
输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5
思路分析:由于题目特意要求 O(n log n) 时间复杂度和常数级空间复杂度 所以不能使用冒泡、计数排序啥的,比较符合要求的就是归并排序。
归并排序:排序一段序列分为排序前部分、后部分,再合并两个已经排序好的部分。
/**
* 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 == NULL || head->next == NULL) {
return head;
}
ListNode *end = head;//定位到链表的尾部
while (end != NULL && end->next != NULL) {
end = end->next;
}
return mergeSort(head, end);
}
//归并排序
ListNode* mergeSort(ListNode* head, ListNode *end) {
if (head == end) {//这段链表只有一个节点
return head;
}
if (head->next == end) {//只有两个节点
if (head->val > end->val) {
int tempVaule = head->val;
head->val = end->val;
end->val = tempVaule;
}
return head;
}
//快慢指针,定位链表中间
ListNode *slowPtr = head, *fastPtr = head;
while (fastPtr != end) {
slowPtr = slowPtr->next;//慢指针走一步
fastPtr = fastPtr->next;//快指针走两步
if (fastPtr != end) {
fastPtr = fastPtr->next;//快指针走两步
}
}
//第一步 递归,排序右半
ListNode * rightList = mergeSort(slowPtr->next, end);
slowPtr->next = NULL;//将左右两部分切开
//第二步 递归,排序左半
ListNode * leftList = mergeSort(head, slowPtr);
//第三步 合并
ListNode *pHead = NULL, *pEnd = NULL;//合并链表的头、尾
if (rightList == NULL) {
return leftList;
}
//初始化头结点、尾节点
if (rightList->val > leftList->val) {
pEnd = pHead = leftList;
leftList = leftList->next;
}
else {
pEnd = pHead = rightList;
rightList = rightList->next;
}
//合并,每次将较小值放入新链表
while (rightList && leftList) {
if (rightList->val > leftList->val) {
pEnd->next = leftList;
pEnd = pEnd->next;
leftList = leftList->next;
}
else {
pEnd->next = rightList;
pEnd = pEnd->next;
rightList = rightList->next;
}
}
//可能某个链表有剩余
if (rightList == NULL) {
pEnd->next = leftList;
}
else {
pEnd->next = rightList;
}
return pHead;
}
};
下面对代码做出优化,去掉链表end的确定。
/**
* 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 == NULL || head->next == NULL) {
return head;
}
return mergeSort(head);//去掉链表尾端的寻找
}
ListNode* mergeSort(ListNode* head) {
if (head == NULL || head ->next == NULL) {//这段链表只有一个节点
return head;
}
//快慢指针,定位链表中间
ListNode *slowPtr = head, *fastPtr = head->next;
while (fastPtr != NULL && fastPtr->next != NULL) {
slowPtr = slowPtr->next;//慢指针走一步
fastPtr = fastPtr->next;//快指针走两步
if (fastPtr != NULL && fastPtr->next != NULL) {
fastPtr = fastPtr->next;//快指针走两步
}
}
//第一步 递归,排序右半
ListNode * rightList = mergeSort(slowPtr->next);
slowPtr->next = NULL;//将左右两部分切开
//第二步 递归,排序左半
ListNode * leftList = mergeSort(head);
//第三步 合并
ListNode *pHead = NULL, *pEnd = NULL;//合并链表的头、尾
if (rightList == NULL) {
return leftList;
}
//初始化头结点、尾节点
if (rightList->val > leftList->val) {
pEnd = pHead = leftList;
leftList = leftList->next;
}
else {
pEnd = pHead = rightList;
rightList = rightList->next;
}
//合并,每次将较小值放入新链表
while (rightList && leftList) {
if (rightList->val > leftList->val) {
pEnd->next = leftList;
pEnd = pEnd->next;
leftList = leftList->next;
}
else {
pEnd->next = rightList;
pEnd = pEnd->next;
rightList = rightList->next;
}
}
//可能某个链表有剩余
if (rightList == NULL) {
pEnd->next = leftList;
}
else {
pEnd->next = rightList;
}
return pHead;
}
};