原题链接: 203. 移除链表元素 - 力扣(Leetcode)
tag: 链表.
一. 题目
给你一个链表的头节点 head
和一个整数 val
, 请你删除链表中所有满足 Node.val == val
的节点, 并返回 新的头节点 .
二. 题解
当要对链表中的节点的进行删除操作时, 必然会涉及头删的情况.
而删除链表的节点的一般方法是锚定待删除节点的前驱节点, 修改前驱节点的 next
指针, 使其指向待删除节点的后继节点, 再 delete
待删除的节点, 即可完成删除操作.
然而头节点没有前驱节点, 当删除头节点时, 我们需要进行额外的讨论.
为了避免这种额外的讨论, 我们引入虚拟头节点( dummy
)的概念.
设置虚拟头节点, 即在链表的头节点前新插入一个节点. 如此, 链表的头节点便有了前驱节点(即 dummy
), 头删时就不需要进行额外的讨论.
移除元素前.
设置一个虚拟头节点 dummy
.
ListNode* dummy = new ListNode(0, head);
开始对指定元素所在节点进行删除操作.
ListNode* curr = dummy;
ListNode* temp = curr->next;
curr->next = temp->next;
delete temp;
逐一检测每个节点中的元素值, 若是指定元素, 则移除该元素; 若不是指定元素, 则 curr
指针向后移一步.
curr 指针向后移一步.
curr = curr->next;
curr 指针向后移一步.
curr = curr->next;
curr 指针向后移一步.
curr = curr->next;
当 curr->next == nullptr
时, 链表中所有的节点都被遍历一次, 指定元素都已经被移除完毕.
返回新的头节点.
head = dummy->next;
delete dummy;
移除元素后.
三. 复杂度分析
时间复杂度: O(N), 其中 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) {
ListNode* dummy = new ListNode(0, head); // 设置一个虚拟头节点
ListNode* curr = dummy;
while (curr->next != nullptr) {
if (curr->next->val == val) { // 对指定元素所在节点进行删除操作
ListNode* temp = curr->next;
curr->next = temp->next;
delete temp;
} else { // curr 指针向后移一步
curr = curr->next;
}
}
head = dummy->next; // 返回新的头节点
delete dummy;
return head;
}
};