在 O(n log n) 時間、O(1) 空間(遞歸棧除外)內對單鏈表排序。顯然需用歸並排序(穩定、鏈表天然適合)或快速排序(鏈表分區困難)。本文採用自頂向下歸並排序。
ListNode* getMid(ListNode* head) {
ListNode *slow = head, *fast = head;
while (fast->next && fast->next->next) { // 關鍵條件
slow = slow->next;
fast = fast->next->next;
}
return slow; // 偶數長度返回前中點
}
fast->next && fast->next->next 確保 slow 停在前中點mid->next = nullptr 分成兩獨立鏈表ListNode* merge(ListNode* a, ListNode* b) {
ListNode dummy(-1), *tail = &dummy;
while (a && b) {
if (a->val <= b->val) tail->next = a, a = a->next;
else tail->next = b, b = b->next;
tail = tail->next;
}
tail->next = a ? a : b; // 掛上剩余部分
return dummy.next;
}
dummy 避免頭節點特判tail 追蹤合併尾部,O(1) 接駁class Solution {
public:
ListNode* sortList(ListNode* head) {
if (!head || !head->next) return head; // 基礎情況
ListNode* mid = getMid(head);
ListNode* right = mid->next;
mid->next = nullptr; // 斷開
return merge(sortList(head), sortList(right));
}
private:
ListNode* getMid(ListNode* head) { /* 同上 */ }
ListNode* merge(ListNode* a, ListNode* b) { /* 同上 */ }
};
| 指標 | 複雜度 | 說明 |
|---|---|---|
| 時間 | O(n log n) | 每層合併 O(n),遞歸深度 log n |
| 空間 | O(log n) | 遞歸調用棧深度;若要求 O(1) 需改迭代法 |
| 穩定性 | 穩定 | 合併時 a->val <= b->val 保持相對序 |