Solution 1
要求线性对数时间复杂度,那只能是归并或者快速排序(其他排序链表实现太难不考虑了),再加之快速排序的调换次数过多,实在不好处理(且对链表实际的复杂度会更高)且不稳定(最坏情况下是 O ( n 2 ) O(n^2) O(n2)),因此这里只考虑归并排序。整体思路如下:
- 找到中点,然后分支(快慢指针,参考 0143. Reorder List )
- 在分支内,完成进一步分支的排序
- 两个分支完成内部排序之后,按顺序归并(合并链表 0021. Merge Two Sorted Lists )
这里面有一个两个小调整,一个是中点的部分,原有的实现会在偶数情况下取左侧那个,因此不方便就重新实现一下;另一个是合并的部分,判断逻辑有点多余,使用假head进行合并。
- 时间复杂度: O ( n log n ) O(n \log n) O(nlogn),其中 n n n为输入链表的节点个数,标准归并排序实现
- 空间复杂度: O ( log n ) O(\log n) O(logn),其中 n n n为输入链表的节点个数,函数递归调用占用
/**
* 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 == nullptr) {
return head;
}
return this->sortList(head, nullptr);
}
private:
ListNode* sortList(ListNode* head, ListNode* tail) {
// head是当前head,tail是尾节点的next
if (head == nullptr) {
return head;
}
if (head->next == tail) {
// 子链表就一个节点
head->next = nullptr;
return head;
}
auto slow = head, fast = head;
while (fast != tail) {
slow = slow->next;
fast = fast->next;
if (fast != tail) {
fast = fast->next;
}
}
auto mid = slow;
return this->merge(this->sortList(head, mid), this->sortList(mid, tail));
}
ListNode* merge(ListNode* l1, ListNode* l2) {
if (l1 == nullptr && l2 == nullptr) {
return nullptr;
}
if (l1 == nullptr) {
return l2;
}
if (l2 == nullptr) {
return l1;
}
auto ans = new ListNode();
auto cur = ans;
while(l1 != nullptr && l2 != nullptr) {
if (l1->val <= l2->val) {
cur->next = l1;
l1 = l1->next;
}
else {
cur->next = l2;
l2 = l2->next;
}
cur = cur->next;
}
if (l1 != nullptr) {
cur->next = l1;
}
else {
cur->next = l2;
}
return ans->next;
}
};
Solution 2
然后我发现有递归调用,不是 O ( 1 ) O(1) O(1)的空间复杂度……
那就得用while循环替代递归了,整体就是从长度1开始,逐渐二倍扩展,对当前小分段内部的进行合并(仅一层递归)。需要额外处理第二个分段可能为空的情形。
- 时间复杂度: O ( n log n ) O(n \log n) O(nlogn),其中 n n n为输入链表的节点个数,标准归并排序实现
- 空间复杂度: O ( 1 ) O(1) O(1),由于while中的调用每次仅一层递归,因此为常数规模的空间复杂度
/**
* 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 == nullptr) {
return head;
}
// 确定length
int length = 0;
auto temp = head;
while (temp != nullptr) {
length++;
temp = temp->next;
}
auto ans = new ListNode();
ans->next = head;
for (int subLength = 1; subLength < length; subLength *= 2) {
auto prev = ans, cur = ans->next;
while (cur != nullptr) {
// 第一个小分段
auto tmp1 = cur;
for (int i = 1; i < subLength && cur->next != nullptr; i++) {
cur = cur->next;
}
// 第二个小分段,需要注意
auto tmp2 = cur->next;
cur->next = nullptr; // 提取第一个分段
cur = tmp2; // 如果为nullptr,就直接跳过(子序列保证有序)
if (cur != nullptr) {
for (int i = 1; i < subLength && cur->next != nullptr; i++) {
cur = cur->next;
}
}
ListNode *nextTmp1 = nullptr; // 下一轮第一个分段的头
if (cur != nullptr) {
nextTmp1 = cur->next;
cur->next = nullptr; // 投递第二个分段
}
auto mergedTmp = this->merge(tmp1, tmp2);
prev->next = mergedTmp;
while (prev->next != nullptr) {
prev = prev->next; // 下一轮的prev就是第二段的最后一个(或者第二段为空时的第一段最后一个)
}
cur = nextTmp1; // 下一轮
}
}
return ans->next;
}
private:
ListNode* merge(ListNode* l1, ListNode* l2) {
if (l1 == nullptr && l2 == nullptr) {
return nullptr;
}
if (l1 == nullptr) {
return l2;
}
if (l2 == nullptr) {
return l1;
}
auto ans = new ListNode();
auto cur = ans;
while(l1 != nullptr && l2 != nullptr) {
if (l1->val <= l2->val) {
cur->next = l1;
l1 = l1->next;
}
else {
cur->next = l2;
l2 = l2->next;
}
cur = cur->next;
}
if (l1 != nullptr) {
cur->next = l1;
}
else {
cur->next = l2;
}
return ans->next;
}
};
Solution 3
Solution 1的Python实现
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if head is None: return head
return self.__sortList(head, None)
def __sortList(self, head: Optional[ListNode], tail: Optional[ListNode]) -> Optional[ListNode]:
if head is None: return head
if head.next == tail:
head.next = None
return head
slow, fast = head, head
while fast != tail:
slow = slow.next
fast = fast.next
if fast != tail: fast = fast.next
mid = slow
return self.__merge(self.__sortList(head, mid), self.__sortList(mid, tail))
def __merge(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
if l1 is None and l2 is None: return None
if l1 is None: return l2
if l2 is None: return l1
ans = ListNode()
cur = ans
while l1 is not None and l2 is not None:
if l1.val <= l2.val:
cur.next = l1
l1 = l1.next
else:
cur.next = l2
l2 = l2.next
cur = cur.next
if l1 is not None: cur.next = l1
else: cur.next = l2
return ans.next
Solution 4
Solution 2的Python实现
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def sortList(self, head: Optional[ListNode]) -> Optional[ListNode]:
if head is None: return head
length = 0
temp = head
while temp is not None:
length += 1
temp = temp.next
ans = ListNode()
ans.next = head
subLength = 1
while subLength < length:
prev = ans
cur = ans.next
while cur is not None:
tmp1 = cur
for i in range (1, subLength):
if cur.next is not None:
cur = cur.next
else: break
tmp2 = cur.next
cur.next = None
cur = tmp2
if cur is not None:
for i in range(1, subLength):
if cur.next is not None:
cur = cur.next
else: break
nextTmp1 = None
if cur is not None:
nextTmp1 = cur.next
cur.next = None
mergedTmp = self.__merge(tmp1, tmp2)
prev.next = mergedTmp
while prev.next is not None: prev = prev.next
cur = nextTmp1
subLength *= 2
return ans.next
def __merge(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
if l1 is None and l2 is None: return None
if l1 is None: return l2
if l2 is None: return l1
ans = ListNode()
cur = ans
while l1 is not None and l2 is not None:
if l1.val <= l2.val:
cur.next = l1
l1 = l1.next
else:
cur.next = l2
l2 = l2.next
cur = cur.next
if l1 is not None: cur.next = l1
else: cur.next = l2
return ans.next