做链表的题目之前一定要把链表这种数据结构完全弄明白,不然做起题目来会很痛苦。
链表是由一连串节点构成的。节点是一个结构体,包含两个数据,一个是数值int,一个是next指针。数值int顾名思义就是储存这个节点的值,而next指针储存的是该节点的下一个节点的地址,通过这个地址就可以找到该节点的下一个节点,形象化地说,就像是该节点用一个箭头指向了下一个节点。这样,每个节点都被上一个节点所指向,它自己本身又指向下一个节点,形象化地说,这些节点就被一个个箭头连接起来了,这,就成了链表。一定一定要理解得非常清楚!
回到这题,要删除链表中的节点,其实不用真的删掉它,只用把该节点的上一个节点的next指针改成该节点的下一个节点的地址就可以了,用形象化的箭头表示,就相当于A->B->C变成了A->C,其实节点B并没有真正被删除,只是脱离了部队,再也找不到罢了。
这题还有一个小技巧就是使用了一个虚拟头节点指向了头节点。这样的好处是,万一头节点是想要删除的那个节点时,也可以统一操作了。不然,没有这个虚拟头节点的话,想要删除头节点,要怎么删除呢?按照我刚刚说的,这个头节点本身就是第一个节点,没有上一个节点,就不存在修改上一个节点的next指针这种操作了。这时,就得针对头节点专门写一段处理逻辑了,看起来就没那么统一了。
最后记得将new出来的虚拟头节点手动释放。
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* cur = dummyHead;
while (cur->next) {
if (cur->next->val == val) {
cur->next = cur->next->next;
}
else {
cur = cur->next;
}
}
head = dummyHead->next;
delete dummyHead;
return head;
}
};