代码随想录算法训练营第三天|203.移除链表元素,707.设计链表,206.反转链表

news/2024/9/28 22:04:54

203.移除链表元素

文章链接:https://programmercarl.com/0203.移除链表元素.html#算法公开课
视频讲解:https://www.bilibili.com/video/BV18B4y1s7R9
题目出处:https://leetcode.cn/problems/remove-linked-list-elements/

卡哥在这里讲解了为什么要使用虚拟头节点,以及使用和不使用的区别,不清楚的话可以看视频讲解

  • 方一:直接删除头节点
    写的时候有几个小问题需要注意,已经在代码中标出
class Solution {
public:ListNode* removeElements(ListNode* head, int val) {//不使用虚拟头节点,直接删除//删除头节点(头节点特殊,删除方式不一样,直接将head后移一个节点)while(head!=NULL&&head->val==val){ //这里一开始写的时候用的if,但是如果head后面的节点依然符合要求,则会漏掉这种情况ListNode* tmp=head;head=head->next;delete tmp;}//删除非头节点ListNode* cur=head;while(cur!=NULL&&cur->next!=NULL){   //这里一开始写的时候没有写cur!=NULL,这样是不行的,因为如果它为空了再操作会导致空指针错误if(cur->next->val==val){ ListNode* tmp=cur->next;cur->next=cur->next->next;delete tmp;}else{cur=cur->next;}}return head;}
};
  • 方二:使用虚拟头节点
    错误如下图所示:

这里会报错的原因是 dummyHead 没有被初始化。dummyHead 是一个指向 ListNode 类型的指针,但没有给它分配内存空间。当前代码只声明了一个指针,但它指向的是未定义的内存区域,因此在访问 dummyHead->next 时会导致未定义行为或崩溃。
所以这里应该写成:

ListNode* dummyHead = new ListNode(0); //
dummyHead->next = head; 

总的代码如下所示:

class Solution {
public:ListNode* removeElements(ListNode* head, int val) {//使用虚拟头节点ListNode* dummyHead=new ListNode(0); //注意将指针初始化dummyHead->next=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;return head;}
};
  • 方三:使用递归也很有意思
class Solution {
public:ListNode* removeElements(ListNode* head, int val) {//使用递归if(head==nullptr){return nullptr;}if(head->val==val){ListNode* newHead=removeElements(head->next,val);delete head;return newHead;}else{head->next=removeElements(head->next,val); //这里一开始没有想到head->nextreturn head;}}
};

707.设计链表

文章链接:https://programmercarl.com/0707.设计链表.html
视频链接:https://www.bilibili.com/video/BV1FU4y1X7WD
题目链接:https://leetcode.cn/problems/design-linked-list/description/

先构造节点,并为类写构造函数进行初始化。

class MyLinkedList {
public://定义节点struct LinkNode{int val;LinkNode* next;LinkNode():next(nullptr){}//构造函数LinkNode(int val):val(val),next(nullptr){}//重载构造函数};MyLinkedList() { //构造函数dummyHead=new LinkNode();size=0;}
private:int size;LinkNode* dummyHead;
};

以下为学校内学到的写法:

  • 头插法:
void addAtHead(int val) {LinkNode* s=new LinkNode(val);s->next=dummyHead->next;dummyHead->next=s;}
  • 尾插法:
void addAtTail(int val) {LinkNode* s=new LinkNode(val);LinkNode* r=dummyHead;while(r->next!=NULL){r=r->next;}r->next=s;size++;}
  • 在index之前插入
void addAtIndex(int index, int val) {if(index>size||index<0){return;}LinkNode* cur=dummyHead;while(index--){cur=cur->next;}LinkNode* s=new LinkNode(val);s->next=cur->next;cur->next=s;size++;}
  • 获取第index个节点值
int get(int index) {if(index>(size-1)||index<0) return -1;LinkNode* cur=dummyHead->next;while(index--){cur=cur->next;}return cur->val;}
  • 删除第index个节点
void deleteAtIndex(int index) {if(index<0||index>=size) return;LinkNode* cur=dummyHead;while(index--){cur=cur->next;}LinkNode* tmp= cur->next;cur->next=cur->next->next;delete tmp;tmp=nullptr;//这里最好将其赋为空指针//delete命令指示释放了tmp指针原本所指的那部分内存,//被delete后的指针tmp的值(地址)并非就是NULL,而是随机值。也就是被delete后,//如果不再加上一句tmp=nullptr,tmp会成为乱指的野指针//如果之后的程序不小心使用了tmp,会指向难以预想的内存空间size--;}

206.反转链表

  • 双指针的写法:
class Solution {
public:ListNode* reverseList(ListNode* head) {ListNode* cur=head;ListNode* pre=nullptr;while(cur!=NULL){ListNode* tmp=cur->next;cur->next=pre;pre=cur;cur=tmp;}return pre;}
};
  • 递归写法:
class Solution {
public:ListNode* reverse(ListNode* pre,ListNode*cur){// if(cur!=NULL){//     ListNode* tmp=cur->next;//     cur->next=pre;//     reverse(cur,tmp);// }// else return pre;if(cur==NULL) return pre;ListNode* tmp=cur->next;cur->next=pre;return reverse(cur,tmp);}ListNode* reverseList(ListNode* head) {ListNode* pre=nullptr;ListNode* cur=head;return reverse(pre,cur);}
};

第一次写,写成了注释掉的那部分,说明对递归还不太熟

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/65934.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

Android页面跳转与返回机制详解

在Android开发中,页面跳转是实现应用功能交互的重要手段之一。本文将从Activity之间的跳转、Activity与Fragment之间的跳转、Fragment之间的跳转以及页面返回的问题四个方面进行详细解析。 一、Activity之间的跳转 Activity是Android应用的基本构建块,代表了一个用户界面的单…

04-Consul服务注册与发现

1.为什么要引入服务注册中心 1.1 原因 public static final String PAYMENT_SRV_URL = "http://localhost:8001";//硬编码微服务所在的IP地址和端口号硬编码到订单微服务中,会存在非常多的问题 (1)如果订单微服务和支付微服务的IP地址或者端口号发生了变化,则支付…

星际战甲:战甲配卡

题记部分 一、永恒烈焰(火鸡)进图开2,随后4技能升温、3技能降温,钢铁地图炮 二、标题三、标题— 业精于勤荒于嬉,行成于思毁于随 —

结对项目——四则运算

结对项目——四则运算这个作业属于哪个课程 软工22级计科12班这个作业的要求在哪里 作业要求这个作业的目标 实现四则运算的结对编程项目成员姓名 学号 GitHub链接 分工谭立业 3122004365 github 项目功能的基本实现,博客的编写罗锴佳 3122001905 github 功能函数的测试与完善…

引用拷贝,浅拷贝,深拷贝

参考资料 水平有限,欢迎交流! kimi 【【每天一个技术点】引用拷贝、浅拷贝、深拷贝】 一文搞懂Java引用拷贝、浅拷贝、深拷贝 - bigsai - 博客园 (cnblogs.com) 【黑马程序员匠心之作|C++教程从0到1入门编程,学习编程不再难】 1. 引用拷贝 (起绰号) 引用拷贝并不是真正意义上…

黑马PM-内容管理-运营管理

消息推送账号管理权限管理日志管理