Day5_203. 移除链表元素
一、今日学习的文章链接和视频链接题目链接https://leetcode.cn/problems/remove-linked-list-elements/视频讲解https://www.bilibili.com/video/BV18B4y1s7R9二、自己看到题目的第一想法看到题目要求删除链表中所有值等于 val 的节点第一反应是链表的删除操作和数组不一样数组是覆盖链表是修改指针指向。最开始想到的思路遍历链表遇到值为 val 的节点就把它的前驱节点的 next 指向当前节点的下一个节点跳过它。但马上意识到一个问题如果要删除的节点是头节点怎么办比如示例 3 全是要删除的节点头节点本身就是目标值处理起来会很麻烦。三、自己实现过程中遇到哪些困难头节点处理困难最开始的代码没有处理头节点为目标值的情况比如输入 [7,7,7,7]val7 时头节点本身要被删除普通的遍历方法无法处理需要额外写逻辑判断头节点是否为目标值代码变得很繁琐。指针操作逻辑混乱在遍历过程中一开始直接用 cur cur.next 来移动指针但是如果当前节点被删除了cur 不应该直接移动否则会跳过下一个节点导致漏删。比如 [1,2,6,6,3]删除第一个 6 后直接移动 cur 会跳过第二个 6。空指针访问问题没有考虑链表为空、链表全是目标节点的情况导致访问 cur.next 时出现空指针异常程序崩溃。前驱节点维护麻烦一开始尝试用一个前驱节点 prev 来记录当前节点的前一个节点但写代码时经常搞混 prev 和 cur 的关系修改指针时容易出错。四、今日收获心得学会了 ** 虚拟头节点哨兵节点** 的用法完美解决了头节点需要删除的问题定义一个虚拟头节点 dummyHead让它的 next 指向原链表的头节点这样所有节点都变成了 “中间节点”处理逻辑统一不需要单独判断头节点。遍历的时候用 cur 从 dummyHead 开始检查 cur.next.val 是否等于 val如果是就修改 cur.next cur.next.next否则 cur cur.next。理解了链表删除的核心逻辑删除节点的本质是让前驱节点的指针直接指向被删节点的后继节点从而跳过被删节点。遍历过程中只有当前节点不需要删除时才移动指针如果删除了节点指针不移动继续检查新的 next 节点。掌握了链表操作的边界处理处理空链表、链表全为目标节点、头节点 / 尾节点为目标节点等特殊情况。写链表题时优先考虑用虚拟头节点简化边界处理逻辑减少代码复杂度。class Solution { public: ListNode* removeElements(ListNode* head, int val) { // 虚拟头节点 ListNode* dummy new ListNode(0); dummy-next head; ListNode* cur dummy; while (cur-next ! nullptr) { if (cur-next-val val) { // 删除节点 ListNode* tmp cur-next; cur-next cur-next-next; delete tmp; } else { cur cur-next; } } ListNode* res dummy-next; delete dummy; return res; } };