給定單鏈表頭節點 head 和整數 val,刪除鏈表中所有值等於 val 的節點,返回新頭節點。
示例:1 → 2 → 6 → 3 → 4 → 5 → 6, val = 6 → 1 → 2 → 3 → 4 → 5
若頭節點值為 val,頭指針需後移;可能連續多個頭節點需刪除。直接處理需特判,代碼繁瑣。
創建一個虛擬節點 dummy 指向 head,統一處理「前驅節點的 next 指向當前節點」的邏輯,無需特判頭節點。
struct ListNode* removeElements(struct ListNode* head, int val) {
struct ListNode dummy;
dummy.next = head;
struct ListNode *prev = &dummy, *curr = head;
while (curr) {
if (curr->val == val) {
// 刪除 curr:prev->next 跳過 curr
struct ListNode* del = curr;
prev->next = curr->next;
curr = curr->next;
free(del); // C 語言釋放記憶體;C++ 用 delete
} else {
// 保留 curr:前移 prev 和 curr
prev = curr;
curr = curr->next;
}
}
return dummy.next;
}
初始:dummy → 1 → 2 → 6 → 3 → 4 → 5 → 6
↑ ↑
prev curr
檢測到 6:prev->next = curr->next (跳過 6)
刪除 6,curr 前移
繼續遍歷直到結束
結果:dummy → 1 → 2 → 3 → 4 → 5
struct ListNode* removeElements(struct ListNode* head, int val) {
if (!head) return NULL;
head->next = removeElements(head->next, val);
return head->val == val ? head->next : head;
}
| 指標 | 迭代 + 虛擬頭 | 遞歸 |
|---|---|---|
| 時間 | O(N) | O(N) |
| 空間 | O(1) | O(N) 棧 |
| 頭節點處理 | 統一,無特判 | 自然處理 |
| 工程推薦度 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ |
free/deleteprev 保持不變,只有保留節點時才 prev = currdummy.next,而非 headcurr->val == curr->next->val虛擬頭節點是鏈表題目的「萬金油」,將邊界條件內化為統一邏輯,極大降低出錯率,是面試與工程中的必備技巧。