例题
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回新的头节点。
示例:
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]
虚拟头结点
- 如果不用虚拟头结点,则需要考虑移除的元素是否是头结点:
- 对于头结点,移除方法是将
head移向head->next - 对于非头结点(包含尾节点),移除方法是将
cur->next赋值为cur->next->next - 因此代码不统一,不简洁
- 对于头结点,移除方法是将
- 使用虚拟头结点
dummyHead,是在head前设置一个节点,从而将链表头结点与非头结点的操作统一起来,此方法适用于链表的多种操作。
// 时间复杂度: O(n)
// 空间复杂度: O(1)
/**
* 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) {
// use dummy node
ListNode *dummyHead=new ListNode;
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;
}
};
- 使用虚拟头结点使得所有节点可以采用同一方法处理,包括尾节点:
- 这里
while的条件使cur最多到倒数第二个节点,而判断条件是cur->next的值是否等于目标值,也就是判断最后一个节点是否需要删除 - 如果需要删除,则
cur->next=cur->next->next,即倒数第二个节点的next指向最后一个节点的next,也就是NULL,这就完成了对尾节点的删除
- 这里
博客围绕链表元素移除例题展开,以LeetCode 203题为例,介绍移除链表中满足特定条件节点的问题。指出不使用虚拟头结点时,处理头结点和非头结点的代码不统一。而使用虚拟头结点可将链表头结点与非头结点操作统一,适用于多种链表操作。
2835





