算法训练营第五天| 203. 链表基础结构与操作
本题最关键是要理解 虚拟头结点的使用技巧这个对链表题目很重要。题目链接https://leetcode.cn/problems/remove-linked-list-elements/视频讲解https://www.bilibili.com/video/BV18B4y1s7R9自己看到题目的第一想法看到题目要删除链表中所有值等于val的节点我第一反应是遍历链表遇到值等于val的节点就删除。但马上想到头节点的处理比较麻烦因为如果要删除头节点需要更新head指针。想到可以用虚拟头节点(dummy node)技巧在真实头节点前面加一个虚拟节点这样所有节点都可以用同样的逻辑处理最后返回dummy-next就行。自己实现过程中遇到哪些困难刚开始没用虚拟头节点直接处理头节点代码很乱各种if判断。删除节点时指针操作容易出错特别是cur-next cur-next-next这一步要先保存要删除的节点。忘记释放删除节点的内存C需要手动delete。边界条件没处理好比如空链表、所有节点都要删除的情况。遍历结束条件没想清楚应该是cur-next ! nullptr而不是cur ! nullptr。测试时发现如果连续多个节点都要删除逻辑会出错需要仔细处理指针移动。今日收获心得学会了虚拟头节点的技巧这个在链表题目中很常用可以简化头节点的特殊处理。掌握了链表删除的标准操作先保存要删除的节点再修改指针最后释放内存。理解了为什么需要while循环而不是if因为可能连续多个节点都要删除。学会了处理链表的边界条件特别是空链表和删除头节点的情况。指针操作要小心一定要先检查指针是否为空再访问其成员。#include iostream using namespace std; 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); dummy-next head; ListNode* cur dummy; while (cur-next ! nullptr) { if (cur-next-val val) { ListNode* temp cur-next; cur-next cur-next-next; delete temp; } else { cur cur-next; } } ListNode* newHead dummy-next; delete dummy; return newHead; } }; void printList(ListNode* head) { ListNode* cur head; while (cur ! nullptr) { cout cur-val ; cur cur-next; } cout endl; } int main() { Solution sol; // 测试用例1: [1,2,6,3,4,5,6], val6 ListNode* head1 new ListNode(1); head1-next new ListNode(2); head1-next-next new ListNode(6); head1-next-next-next new ListNode(3); head1-next-next-next-next new ListNode(4); head1-next-next-next-next-next new ListNode(5); head1-next-next-next-next-next-next new ListNode(6); cout 原始链表: ; printList(head1); ListNode* result1 sol.removeElements(head1, 6); cout 删除6后: ; printList(result1); // 测试用例2: [], val1 ListNode* head2 nullptr; ListNode* result2 sol.removeElements(head2, 1); cout 空链表删除1后: ; printList(result2); // 测试用例3: [7,7,7,7], val7 ListNode* head3 new ListNode(7); head3-next new ListNode(7); head3-next-next new ListNode(7); head3-next-next-next new ListNode(7); cout 原始链表: ; printList(head3); ListNode* result3 sol.removeElements(head3, 7); cout 删除7后: ; printList(result3); // 测试用例4: [1,2,3], val4 (没有要删除的) ListNode* head4 new ListNode(1); head4-next new ListNode(2); head4-next-next new ListNode(3); cout 原始链表: ; printList(head4); ListNode* result4 sol.removeElements(head4, 4); cout 删除4后: ; printList(result4); return 0; }