對單鏈表排序,時間 O(n log n),空間 O(1) (不計遞歸棧)。
數組歸並需 O(n) 輔助空間,但鏈表**合併兩個有序鏈表只需 O(1) 空間** (僅調整指針)。
關鍵步驟:
// C++
class Solution {
public:
ListNode* sortList(ListNode* head) {
if (!head || !head->next) return head;
return mergeSort(head);
}
private:
ListNode* mergeSort(ListNode* head) {
if (!head || !head->next) return head;
// 快慢指針找中點
ListNode *slow = head, *fast = head, *pre = nullptr;
while (fast && fast->next) {
fast = fast->next->next;
pre = slow;
slow = slow->next;
}
pre->next = nullptr; // 斷開
ListNode* l1 = mergeSort(head);
ListNode* l2 = mergeSort(slow);
return merge(l1, l2);
}
ListNode* merge(ListNode* l1, ListNode* l2) {
ListNode dummy(0), *tail = &dummy;
while (l1 && l2) {
if (l1->val <= l2->val) { tail->next = l1; l1 = l1->next; }
else { tail->next = l2; l2 = l2->next; }
tail = tail->next;
}
tail->next = l1 ? l1 : l2;
return dummy.next;
}
};
// Java
class Solution {
public ListNode sortList(ListNode head) {
if (head == null || head.next == null) return head;
return mergeSort(head);
}
private ListNode mergeSort(ListNode head) {
if (head == null || head.next == null) return head;
ListNode slow = head, fast = head, pre = null;
while (fast != null && fast.next != null) {
fast = fast.next.next;
pre = slow;
slow = slow.next;
}
pre.next = null;
ListNode l1 = mergeSort(head);
ListNode l2 = mergeSort(slow);
return merge(l1, l2);
}
private ListNode merge(ListNode l1, ListNode l2) {
ListNode dummy = new ListNode(0), tail = dummy;
while (l1 != null && l2 != null) {
if (l1.val <= l2.val) { tail.next = l1; l1 = l1.next; }
else { tail.next = l2; l2 = l2.next; }
tail = tail.next;
}
tail.next = (l1 != null) ? l1 : l2;
return dummy.next;
}
}