打卡第三十五天
题目:在 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(1),因此不能使用递归。因此这里使用 bottom-to-up 的算法来解决,参考大佬的算法步骤来写。
首先须掌握三个知识点:1.merge(l1, l2),双路归并
2.cut(l, n),将链表 l 切掉前 n 个节点,并返回后半部分的链表头。
3.dummyHead 算法。(自己得上网搜搜看看概念)
通过对数组中的元素进行依次分组归并,逐个排序,最后得到整个元素的有序排列。
链接:https://leetcode-cn.com/submissions/detail/31637980/
如图:`/**
-
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) {
ListNode dummyHead(0);
dummyHead.next = head;
auto p = head;
int length = 0;
while § {
++length;
p = p->next;
}for (int size = 1; size < length; size <<= 1) { auto gpw = dummyHead.next; auto tail = &dummyHead; while (gpw) { auto left = gpw; auto right = cut(left, size); gpw = cut(right, size); tail->next = merge(left, right); while (tail->next) { tail = tail->next; } } } return dummyHead.next;
}
ListNode* cut(ListNode* head, int n) {
auto p = head;
while (–n && p) {
p = p->next;
}if (!p) return nullptr; auto next = p->next; p->next = nullptr; return next;
}
ListNode* merge(ListNode* l1, ListNode* l2) {
ListNode dummyHead(0);
auto p = &dummyHead;
while (l1 && l2) {
if (l1->val < l2->val) {
p->next = l1;
p = l1;
l1 = l1->next;
} else {
p->next = l2;
p = l2;
l2 = l2->next;
}
}
p->next = l1 ? l1 : l2;
return dummyHead.next;}
};`