題目網址:https://leetcode.cn/problems/sort-list/
題意:給一 linked list 的起始節點 head
, 返回以升序排列過的 linked list。
進階:設計 $O(n \cdot log(n))$ time 且 $O(1)$ space 的演算法


Solution 1:
想法:利用 Merge Sort (top-down)

class Solution { public: ListNode* sortList(ListNode* head) { if (!head || !head->next) { return head; }
ListNode *slow = head; ListNode *fast = head->next;
while (fast && fast->next) { slow = slow->next; fast = fast->next->next; }
ListNode *mid = slow->next; slow->next = nullptr;
return merge(sortList(head), sortList(mid)); }
private: ListNode* merge(ListNode* l1, ListNode* l2){ ListNode *dummy = new ListNode(), *tail = dummy;
while (l1 && l2) { if (l1->val > l2->val) { swap(l1, l2); }
tail->next = l1; l1 = l1->next; tail = tail->next; }
tail->next = l1 ? l1 : l2;
return dummy->next; } };
|
- time:$O(n \cdot log(n))$ ➔ Merge Sort 的時間複雜度, $T(n) = 2 \cdot T(\dfrac{n}{2}) + O(n)$
- 每回合的合併需要花:$O(n)$
- 回合數:$O(log(n))$
- space:$O(n)$ ➔ $O(n + log(n))$
- $O(n)$:merge 後的 linked list 長度最多為
n
- $O(log(n))$:取決於遞迴深度, 最大遞迴深度為 log(n)
Solution 2:
想法:利用 Merge Sort (bottom-up)

class Solution { public: ListNode* sortList(ListNode* head) { if (!head || !head->next) { return head; }
const int len = getLen(head); ListNode *dummy = new ListNode(0, head);
for (int n = 1; n < len; n <<= 1) { ListNode *cur = dummy->next; ListNode *tail = dummy;
while (cur) { ListNode *left = cur; ListNode *right = split(left, n); cur = split(right, n); const auto merged = merge(left, right); tail->next = merged.first; tail = merged.second; } } return dummy->next; }
private: int getLen(ListNode* head){ int len = 0; while (head) { ++len; head = head->next; } return len; }
ListNode* split(ListNode* head, int n){ while (--n && head) { head = head->next; }
ListNode *rest = head ? head->next : nullptr;
if (head) { head->next = nullptr; }
return rest; }
pair<ListNode*, ListNode*> merge(ListNode* l1, ListNode* l2){ ListNode *dummy = new ListNode(), *tail = dummy; while (l1 && l2) { if (l1->val > l2->val) { swap(l1, l2); }
tail->next = l1; l1 = l1->next; tail = tail->next; }
tail->next = l1 ? l1 : l2;
while (tail->next) { tail = tail->next; }
return {dummy->next, tail}; } };
|
- time:$O(n \cdot log(n))$ ➔ Merge Sort 的時間複雜度
- space:$O(1)$ ➔ 用 loop 模擬 recursive, 因此只需常數空間