例题
给你一个链表的头节点 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
,这就完成了对尾节点的删除
- 这里