河源市网站建设_网站建设公司_表单提交_seo优化
2026/1/16 20:22:37 网站建设 项目流程

第三天|203.移除链表元素 707.设计链表 206.反转链表

203.移除链表元素

203.移除链表元素 | 代码随想录

手把手带你学会操作链表 | LeetCode:203.移除链表元素_哔哩哔哩_bilibili

笔记

如果没有虚拟头节点,删除操作要分情况,分为头节点和非头节点。

使用虚拟头节点的方法能够让删除/添加操作统一化。

c++需要从内存中释放那个被删除的结点。

使用cur遍历的时候,我们删除的对象一定是cur->next ,因为我们需要删除那个结点的前一个结点地址

返回的时候应该是dummyHead->next ,因为可能头节点已经被删除掉了。

实操出现问题:

newdelete

注意ListNode* dummyHead = new ListNode(0) ,要新开辟内存。

代码/对比

我自己的:

class Solution {
public:ListNode* removeElements(ListNode* head, int val) {ListNode* dummyhead=new ListNode(0);//虚拟头节点dummyhead->next=head;auto cur=dummyhead;//从虚拟头节点的下一个结点(原本链表的头节点)开始遍历,也就是说,当前遍历的那个节点是cur->next而不是curwhile(cur->next!=nullptr)//循环条件:处理的那个结点非空{if(cur->next->val==val){cur->next=cur->next->next;}elsecur=cur->next;}return dummyhead->next;}
};

其他:

class Solution {
public:ListNode* removeElements(ListNode* head, int val) {ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点dummyHead->next = head; // 将虚拟头结点指向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;}
};

注意删除不必要的节点和虚拟头节点

707.设计链表

帮你把链表操作学个通透!LeetCode:707.设计链表_哔哩哔哩_bilibili

707.设计链表 | 代码随想录

笔记

注意index 的起始位置。

添加node的时候注意先后顺序。

实操出现的问题

循环中修改了_size的大小,注意不要修改类似敏感参数。

代码/对比

我自己的:

class MyLinkedList {
public:
struct LinkedNode {int val;LinkedNode* next;LinkedNode(int val):val(val), next(nullptr){}};MyLinkedList() {_dummyHead = new LinkedNode(0); // 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点_size = 0;}int get(int index) {if(index<0||index>(_size-1))//如果index无效{return -1;}LinkedNode* cur=_dummyHead;//cur->next表示当前遍历的值while(index--){cur=cur->next;}return cur->next->val;}void addAtHead(int val) {LinkedNode* node=new LinkedNode(0);//创建一个新的节点node->val=val;node->next=_dummyHead->next;_dummyHead->next=node;_size++;//注意要自增}void addAtTail(int val) {//先找到最后一个节点LinkedNode* cur=_dummyHead;while(cur->next!=nullptr){cur=cur->next;}//此时cur指向最后一个节点//再添加节点LinkedNode* node=new LinkedNode(0);node->next=nullptr;node->val=val;cur->next=node;_size++;}void addAtIndex(int index, int val) {if(index>_size)//如果index无效{return;}if(index==_size)//如果等于长度,则调用addAtTtail{addAtTail(val);return;}if(index<0)//如果小于0则在开头加;{index=0;}//找到indexLinkedNode* cur=_dummyHead;//cur->next表示当前遍历的值while(index--){cur=cur->next;}//插入新的节点LinkedNode* node=new LinkedNode(0);node->val=val;node->next=cur->next;cur->next=node;//size自增_size++;}void deleteAtIndex(int index) {if(index<0||index>_size-1)//如果index无效{return;}//找到indexLinkedNode* cur=_dummyHead;//cur->next是当前遍历的值while(index--){cur=cur->next;}//删除cur->nextLinkedNode* temp=cur->next;cur->next=cur->next->next;delete temp;temp=nullptr;//size自减_size--;}private:int _size;LinkedNode* _dummyHead;
};

206.反转链表

206.反转链表 | 代码随想录

帮你拿下反转链表 | LeetCode:206.反转链表 | 双指针法 | 递归法_哔哩哔哩_bilibili

笔记

双指针法:

一个pre一个cur指针,遍历完全整个链表,对逐个指针翻转指向即可。

注意循环条件为while(cur)而不是while(pre),因为最后需要一个头指针,最后返回的pre就是那个头指针。

递归法:

递归复习:

递归的基本思想是某个函数直接或者间接地调用自身,这样原问题的求解就转换为了许多性质相同但是规模更小的子问题。求解时只需要关注如何把原问题划分成符合条件的子问题,而不需要过分关注这个子问题是如何被解决的。

递归的三个注意点:

1.函数要干什么?

2.递归的停止条件?

3.怎么把大问题转换为小问题?

对于这个问题:

1.函数是为了反转链表,大体逻辑和上边的双指针方法相同;

2.递归的停止条件是while(cur)

3.怎么把大问题转换为小问题:cur指针和pre指针往前移动。

实操出现问题

双指针法:一定要注意循环条件

代码/对比

双指针:

class Solution {
public:ListNode* reverseList(ListNode* head) {ListNode* pre=nullptr;ListNode* cur=head;while(cur)//直到pre指针为空,停止{ListNode* temp=cur->next;cur->next=pre;pre=cur;cur=temp;}return pre;}
};

递归:

我自己的:

class Solution {
public:ListNode* reverse(ListNode* pre, ListNode* cur){//停止条件:if(cur==nullptr){return pre;}else//怎么把大问题转换为小问题:方向反转、pre和cur指针后移{ListNode* tmp=cur->next;cur->next=pre;pre=cur;cur=tmp;return reverse(pre,cur);}}ListNode* reverseList(ListNode* head) {return reverse(nullptr,head);}
};

随想录上面的:

class Solution {
public:ListNode* reverse(ListNode* pre,ListNode* cur){if(cur == NULL) return pre;ListNode* temp = cur->next;cur->next = pre;// 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步// pre = cur;// cur = temp;return reverse(cur,temp);}ListNode* reverseList(ListNode* head) {// 和双指针法初始化是一样的逻辑// ListNode* cur = head;// ListNode* pre = NULL;return reverse(NULL, head);}};

注意return那块可以直接用cur和tmp;

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询