LeetCode 21 基礎題目:合併兩個已排序的單向鏈表,返回新的有序鏈表。核心考察指針操作、邊界條件處理與虛擬頭節點技巧。
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
// 邊界條件:任一為空直接返回另一個
if (!l1) return l2;
if (!l2) return l1;
ListNode dummy(0); // 虛擬頭節點,簡化頭部插入邏輯
ListNode* 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;
}
};
無 dummy: 需特殊處理 head 選擇、head 移動 有 dummy: 統一用 tail->next 插入,最後返回 dummy.next
l1 或 l2 為空的情況不創建新節點,直接重組現有節點的 next 指針,空間複雜度 O(1)。
| 指標 | 複雜度 |
|---|---|
| 時間 | O(m + n) |
| 空間 | O(1) |
| 案例 | 輸入 | 輸出 |
|---|---|---|
| 一般情況 | 1→3→5, 2→4→6 | 1→2→3→4→5→6 |
| 一空 | NULL, 1→2 | 1→2 |
| 全空 | NULL, NULL | NULL |
| 單節點 | 1, 2 | 1→2 |
| 重複值 | 1→1→2, 1→3 | 1→1→1→2→3 |
tail = tail->next → 死循環或丟失節點ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
if (!l1) return l2;
if (!l2) return l1;
if (l1->val < l2->val) {
l1->next = mergeTwoLists(l1->next, l2);
return l1;
} else {
l2->next = mergeTwoLists(l1, l2->next);
return l2;
}
}
// 空間複雜度 O(m+n) 遞歸棧,不推薦大數據量使用