13.排序链表
算法描述
给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
原题链接
https://leetcode-cn.com/problems/sort-list/
样例
示例一:
输入:head = [4,2,1,3]
输出:[1,2,3,4]
示例二:
输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]
示例三:
输入:head = []
输出:[]
解法一
思路
复杂度分析,n为链表长度
时间复杂度分析:
根据二分法可知,时间复杂度为O(nlogn)
空间复杂度分析:O(logn)
对数组做归并排序的空间复杂度为O(n),分别由新开辟数组O(n)和递归函数调用O(logn)组成,而根据链表特性:
数组额外空间:链表可以通过修改引用来更改节点顺序,无需像数组一样开辟额外空间;
递归额外空间:递归调用函数将带来O(logn)的空间复杂度,因此若希望达到O(1)空间复杂度,则不能使用递归。
代码
/**
* 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) {
return sortList(head, nullptr);
}
ListNode* sortList(ListNode* head, ListNode* tail) {
if (head == nullptr) {
return head;
}
if (head->next == tail) {
head->next = nullptr;
return head;
}
ListNode* slow = head, *fast = head;
while (fast != tail) {
slow = slow->next;
fast = fast->next;
if (fast != tail) {
fast = fast->next;
}
}
ListNode* mid = slow;
return merge(sortList(head, mid), sortList(mid, tail));
}
ListNode* merge(ListNode* head1, ListNode* head2) {
ListNode* dummyHead = new ListNode(0);
ListNode* temp = dummyHead;
ListNode* temp1 = head1;
ListNode* temp2 = head2;
while (temp1 != nullptr && temp2 != nullptr) {
if (temp1->val <= temp2->val) {
temp->next = temp1;
temp1 = temp1->next;
} else {
temp->next = temp2;
temp2 = temp2->next;
}
temp = temp->next;
}
if (temp1 != nullptr) {
temp->next = temp1;
}
if (temp2 != nullptr) {
temp->next = temp2;
}
return dummyHead->next;
}
};
解法二
思路
复杂度分析
时间复杂度分析:
空间复杂度分析: