在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。
示例 1:
输入: 4->2->1->3 输出: 1->2->3->4
示例 2:
输入: -1->5->3->4->0
输出: -1->0->3->4->5
链表长度范围是[0, 5 * 104], 节点值范围是-105 <= Node.val <= 105
思路:
这是一道中等难度的题目。一个简单的思路是,把整个链表塞进一个vecor<int>并用STL的sort来排序,完成之后再用指针把每个元素链接起来。但这个思路只是调用了sort函数。对于这道题,至少应该实际写一下排序的算法。(事实上这道题这么做的话会超时)
看到链表排序这一主题,意识到这不是线性表。快速排序和堆排序并不适合链表,快速排序需要快速定位pivot而堆排序需要顺序地表示一个堆。而基数排序就更不适合该场景了——基数排序适用于多关键字的场景。因此插入排序/交换排序/归并排序比较适合链表结构,插入排序达不到O(n logn),交换排序也是如此,所以要满足O(nlogn) 复杂度,只能使用归并排序。
AC代码:
不能行的插入排序,贼慢,差一点就超时了:
/**
* 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 || !head->next) return head;
ListNode* sortedHead = new ListNode(0);
sortedHead->next = head;
ListNode* lastSorted = head;
ListNode* curr = head->next;
while (curr) {
if (lastSorted->val <= curr->val) {
lastSorted = lastSorted->next;
} else {
ListNode* prev = sortedHead;
while (prev->next->val <= curr->val) {
prev = prev->next;
}
lastSorted->next = curr->next;
curr->next = prev->next;
prev->next = curr;
}
curr = lastSorted->next;
}
ListNode* result = sortedHead->next;
delete sortedHead;
return result;
}
};Code language: C++ (cpp)
能行的归并排序:
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
if (!head || !head->next) return head;
ListNode* mid = findMiddle(head);
ListNode* rightHead = mid->next;
mid->next = nullptr;
ListNode* left = sortList(head);
ListNode* right = sortList(rightHead);
return merge(left, right);
}
private:
ListNode* findMiddle(ListNode* head) {
ListNode* slow = head;
ListNode* fast = head->next;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
ListNode* merge(ListNode* l1, ListNode* l2) {
ListNode dummy(0);
ListNode* tail = &dummy;
while (l1 && l2) {
if (l1->val <= l2->val) {
tail->next = l1;
l1 = l1->next;
} else {
tail->next = l2;
l2 = l2->next;
}
tail = tail->next;
}
tail->next = l1 ? l1 : l2;
return dummy.next;
}
};Code language: C++ (cpp)