题源: 203. 移除链表元素
-
创建虚拟头结点:函数首先创建一个值为 0 的虚拟头结点
dummyHead
。虚拟头结点的next
指针指向链表的真实头结点head
。这样做的好处是可以统一处理头结点和非头结点的删除操作,特别是当头结点也需要被删除时。 -
初始化遍历指针:使用一个指针
cur
(当前指针),并将其初始化为指向虚拟头结点dummyHead
。这个指针将用于遍历整个链表。 -
遍历链表:使用一个循环,让
cur
指针遍历整个链表。循环的条件是cur->next
不为NULL
,这意味着只要当前指针的下一个结点存在,循环就会继续。 -
删除操作:在每次循环中,首先检查
cur
指针的下一个结点(即cur->next
)的值是否等于给定的val
:- 如果等于
val
,则需要删除这个结点。首先,保存这个要删除的结点的指针到tmp
,然后调整cur->next
指针,使其指向tmp
的下一个结点(即cur->next->next
)。这样就从链表中移除了tmp
指向的结点。之后,释放(删除)tmp
指向的结点的内存。 - 如果不等于
val
,则简单地将cur
指针移动到下一个结点。
- 如果等于
-
更新真实头结点:循环完成后,将真实头结点
head
更新为dummyHead->next
,因为在删除过程中,原始的头结点可能已经被删除。 -
清理虚拟头结点:在返回新的头结点之前,删除
dummyHead
结点以释放它占用的内存。 -
返回更新后的链表头:最后,函数返回新的头结点
head
。
通过使用虚拟头结点,避免在删除头结点时需要特殊处理的复杂性,并确保了代码的整洁和效率。这种方法在处理链表问题时非常实用,特别是在需要频繁删除头结点或多个连续结点时。
Code
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* dummyHead = new ListNode(0); // 创建一个虚拟结点
dummyHead->next = head;
ListNode* cur = dummyHead;
while (cur->next != NULL) {
if (cur->next->val == val) {
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
} else {
cur = cur->next;
}
}
head = dummyHead->next;
delete dummyHead;
return head;
}
};