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

news/2024/9/28 22:04:21/文章来源:https://www.cnblogs.com/VickyWu/p/18438491

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.hqwc.cn/news/805414.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

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地址或者端口号发生了变化,则支付…

SMOI-R1 赛后若干个月的总结

关于我只差一个许多人 AC 的题目就能与另一个人瓜分 $20$ 块钱这件事。打得非常好的一场比赛,所以才来写总结。 T1 「SMOI-R1」Queue 打表找规律题,太签到了,不讲。 T2 「SMOI-R1」Company 首先,如果要使得 \(x,y\) 的距离最后是尽可能远的,我们就要考虑一些满足最优解的性…

星际战甲:战甲配卡

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

结对项目——四则运算

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

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

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

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

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

Blender快速入门教程1简介

0 简介Blender是最著名的 3D 计算机图形制作免费程序之一。有了 Blender,你可以创建角色、道具、环境以及你的想象力所能产生的几乎所有其他东西。它不仅可以创建对象。你还可以让它们运动起来。在动画中讲述一个故事,带领人们穿越你自己创造的世界,或者为一些视频片段添加特…

今天我有博客了!

今天我有博客了!我要把我的编程心得写下来。 今天,我先写了蜗牛打怪兽。我发现需要打的次数都是2^(n)-1,于是我用while循环求出是2的几次方,再用变量一直乘2,最后-1。以下是具体示例。接着,我写了POW。这题限制比较紧,所以不能直接算,得看c是奇数还是偶数:偶数比绝对值…

『模拟赛』csp-s模拟赛6

『模拟赛』csp-s模拟赛6『模拟赛』csp-s模拟赛6 挂分日寄:0+20+0+0 喵喵赛时对拍拍了10000个点都没拍出来,赛后一下就拍出错来了,我谔谔。 T1 DP喵~ 首先 sort 一遍方便处理 其实转移时加一个 abs 取绝对值就可,纯纯多此一举 设 \(f[i,j,1/0]\) 为前 \(i\) 个数中选 \(j\) …