代码随想录算法训练营DAY3| C++链表Part.1|LeetCode:203.移除链表元素、707.设计链表、206.反转链表

文章目录

  • 203.移除链表元素
    • 直接操作原链表
    • 虚拟头结点
  • 707.设计链表
    • 定义链表结构体
    • `MyLinkedList()` 初始化 `MyLinkedList` 对象。
    • `int get(int index)`
    • `void addAtHead(int val)`
    • `void addAtTail(int val)`
    • `void addAtIndex(int index, int val)`
    • `void deleteAtIndex(int index)`
    • `void printLinkedList()`
  • 206.反转链表
    • 双指针
    • 迭代法

203.移除链表元素

力扣题目链接

文章链接:203.移除链表元素

视频链接:手把手带你学会操作链表 | LeetCode:203.移除链表元素

状态:循环条件的设置while(cur)和while(cur->next != nullptr)

虚拟头结点在链表内容中非常实用,这里分别用两种方法解决该问题。

循环条件的设置while(cur)和while(cur->next != nullptr)有什么不同呢

主要是关注我们在操作链表时,cur应该出现在哪里,如果我们待删除的结点是targetNode,那么我们的cur应该在targetNode的前一个位置,所以循环条件必须是while(cur->next != nullptr)

直接操作原链表

不使用虚拟头结点的话,我们就要考虑如果要删除的结点就是头结点怎么办?这个时候我们需要分情况讨论。

class Solution {
public:ListNode* removeElements(ListNode* head, int val) {// 删除头结点while (head != NULL && head->val == val) { // 注意这里不是ifListNode* tmp = head;head = head->next;delete tmp;}// 删除非头结点ListNode* cur = head;while (cur != NULL && cur->next!= NULL) {if (cur->next->val == val) {ListNode* tmp = cur->next;cur->next = cur->next->next;delete tmp;} else {cur = cur->next;}}return head;}
};

有以下几个重要的点:

  • 一定要先检测头结点,并且,很有可能从头开始连续好几个结点都是val,所以我们一定要用while循环来删除头结点
  • 注意删除非头结点时while的条件:首先要保证cur不等于空然后cur的下一个结点也不是空,因为这代表了最后一个结点,我们是无法进行操作的。

虚拟头结点

class Solution {
public:ListNode* removeElements(ListNode* head, int val) {ListNode* dummyHead = new ListNode(0);dummyHead->next = head;ListNode* cur = dummyHead;while (cur->next != nullptr) // 更改循环条件为cur->next不为nullptr{if (cur->next->val == val) {ListNode* temp = cur->next; // 保存当前要删除的节点cur->next = cur->next->next; // 删除操作delete temp; // 释放内存} else {cur = cur->next; // 当前节点不需要删除,cur指针前进}}ListNode* resultHead = dummyHead->next;delete dummyHead; // 删除虚拟头节点return resultHead;}
};

需要注意的是循环体内的if…else逻辑,因为如果如果执行完删除操作,cur应该位置不变,再看下一个结点是否为要删除的元素。所以一定要接else cur=cur->next

if ()
{ 
}
else{  
}

707.设计链表

力扣题目链接

文章链接:707.设计链表

视频链接:帮你把链表操作学个通透!LeetCode:707.设计链表

状态:如何定义链表结构体不知道,初始化链表没有定义_size。然后许多加减操作都忘记操作_size了。

​ 关于函数void deleteAtIndex(int index)其中对于temp = nullptr的操作非常重要

定义链表结构体

struct LinkedNode
{int val;LinkedNode* next;LinkedNode(int val):val(val), next(nullptr){}
}

MyLinkedList() 初始化 MyLinkedList 对象。

MyLinkedList()
{_dummyhead = new LinkedNode(0);	// 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结_size = 0;
}

int get(int index)

获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1

int get(int index)
{//下标无效if (index > (_size - 1) || index < 0)return -1;LinkedNode* cur = _dummyhead->next; //指向cur指向真正的头结点,因为真正头结点的下标为0while(index--)// 如果--index 就会陷入死循环{cur = cur->next;}return cur->val;
}

void addAtHead(int val)

将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。

void addAtHead(int val)
{LinkedNode* newNode = new LinkedNode(val);//并不需要tempListNode* temp = _dummyhead->next;newNode->next = _dummyhead->next;_dummyhead->next = newNode;_size++;
}

void addAtTail(int val)

将一个值为 val 的节点追加到链表中作为链表的最后一个元素。

void addAtTail(int val)
{LinkedNode* newNode = new LinkedNode(val);LinkedNode* cur = _dummyhead;while (cur->next != null){cur = cur->next;}//该句话可以省略newNode->next = nullptr;cur->next = newNode;_size++;
}

void addAtIndex(int index, int val)

将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。

void addAtIndex(int index, int val)
{LinkedNode* newNode = new LinkedNode(val);LinkedNode* cur = _dummyHead;//判断插入条件if (index > _size)return ;if (index < 0) index = 0;while (index--){cur = cur->next;}newNode->next = cur->next;cur->next = newNode;_size++;
}

void deleteAtIndex(int index)

如果下标有效,则删除链表中下标为 index 的节点。

void deleteAtIndex(int index) 
{//下标无效的情况if (index >= _size || index < 0)return;LinkedNode* cur = _dummyHead;while(index--) {cur = cur ->next;}LinkedNode* tmp = cur->next;cur->next = cur->next->next;delete tmp;//delete命令指示释放了tmp指针原本所指的那部分内存,//被delete后的指针tmp的值(地址)并非就是NULL,而是随机值。也就是被delete后,//如果不再加上一句tmp=nullptr,tmp会成为乱指的野指针//如果之后的程序不小心使用了tmp,会指向难以预想的内存空间tmp=nullptr;_size--;
}

void printLinkedList()

打印链表

// 打印链表
void printLinkedList() {LinkedNode* cur = _dummyHead;while (cur->next != nullptr) {cout << cur->next->val << " ";cur = cur->next;}cout << endl;
}

206.反转链表

力扣题目链接

文章链接:206.反转链表

视频链接:帮你拿下反转链表 | LeetCode:206.反转链表

状态:双指针基本思路都没啥问题,主要就是pre指针的指向出了大问题,不是它指向null,而是它就是null这样才能。进阶的迭代法学习…

双指针

class Solution {
public:ListNode* reverseList(ListNode* head) {ListNode* temp; // 保存cur的下一个节点ListNode* cur = head;ListNode* pre = NULL;while(cur) {temp = cur->next;  // 保存一下 cur的下一个节点,因为接下来要改变cur->nextcur->next = pre; // 翻转操作// 更新pre 和 cur指针pre = cur;cur = temp;}return pre;}
}

迭代法

迭代法应该怎么去想呢?就是说,我们双指针法的本质,也不过就是不停得尽兴交换,这个时候想直接写出迭代函数最好的方法其实就是模拟一下前几个的操作。

假设有一个不停迭代操作pre、cur的函数。这个函数应该怎么写呢?先写出它的终止条件

reverse(pre, cur)//先写明迭代法的终止条件if (cur == NULL) return pre;//这是由于此时pre已经是新的头结点了ListNode* temp = cur->next;cur->next = pre;//之前我们做的操作是pre = cur; cur = temp;来进行指针的移动//如果利用迭代函数,其实就是把这两个参数按照对应位置传进去就好了return reverse(cur, temp)

C++代码如下

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);}};

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

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

相关文章

Python程序设计 模块和包

1. 模块和包 1.1 模块&#xff1a; 一个 py 文件&#xff0c;就是一个模块&#xff0c;文件中包括定义的函数和类等信息。 尽管可以 import 多次&#xff0c;实际上模块只导入一次 模块搜索路径内存中已经加载的模块 -> 内置模块 -> sys.path路径&#xff08;导模块的…

Springboot快速整合bootstrap-table使用,接口对接

这个表格加持还是不错了&#xff0c;自带了全局搜索&#xff0c;分页&#xff0c;数据导出&#xff0c;卡片视图&#xff0c;等&#xff0c;本次整合添加了数据添加弹窗和编辑数据回显弹窗&#xff0c;附完整页面代码&#xff0c;只需要拿过来替换自己实际的接口即可。 效果图 …

鸿蒙实战开发-如何通过拖动滑块调节应用内字体大小

介绍 本篇Codelab将介绍如何使用基础组件Slider&#xff0c;通过拖动滑块调节应用内字体大小。要求完成以下功能&#xff1a; 实现两个页面的UX&#xff1a;主页面和字体大小调节页面。拖动滑块改变字体大小系数&#xff0c;列表页和调节页面字体大小同步变化。往右拖动滑块字…

ppp验证实验

实际操作图 1&#xff0c;IP划分分配 [r1]interface Serial 4/0/0 [r1-Serial4/0/0]ip add 192.168.1.1 24 [r2]interface Serial 4/0/0 [r2-Serial4/0/0]ip address 192.168.1.2 24 [r2]int Mp-group 0/0/0 [r2-Mp-group0/0/0]ip add 192.168.2.1 24 [r3]int Mp-group 0/…

Xcode Launching “XXX“ is taking longer than expected

文章目录 1.问题2.如何进入iOS DeviceSupport目录3.解决方法4.参考博客 1.问题 LLDB is likely reading from device memory to resolve symbols 2.如何进入iOS DeviceSupport目录 3.解决方法 进入iOS DeviceSupport目录&#xff0c;删除该真机对应的架构文件&#xff08;比如…

QT作业day3

1、使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是…

JMeter 如何并发执行 Python 脚本

要在JMeter中并发执行Python脚本&#xff0c;可以使用Jython脚本或通过调用外部Python脚本的方式实现。 使用Jython脚本并发执行Python脚本的步骤&#xff1a; 1、创建一个线程组&#xff1a;在JMeter界面中&#xff0c;右键点击测试计划&#xff0c;选择 “添加” -> “线…

c语言文件操作(下)

目录 1.文件的随机读写1.1 fseek1.2 ftell1.3 rewind 2. 文件结束的判定2.1 文本文件读取结束的判断2.2 二进制文件读取结束的判断 3. 文件缓冲区 1.文件的随机读写 1.1 fseek 根据⽂件指针的位置和偏移量来定位⽂件指针。 函数原型&#xff1a; int fseek (FILE * stream,…

Springboot+vue的企业质量管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的企业质量管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09…

黑马头条day5总结

1、surefire-reports for the individual test results. 借鉴&#xff1a;【已解决】surefire-reports for the individual test results.-CSDN博客 Please refer to D:\javashizhan01\heima-leadnews\heima-leadnews-service\heima-leadnews-article\target\surefire-report…

HTML(二)---【常见的标签使用】

零.前言 本文只介绍常见的标签使用&#xff0c;其中使用的一些HTML专业术语可以在作者的第一篇文章&#xff1a; HTML&#xff08;一&#xff09;---【基础】-CSDN博客中找到。 一.<b>粗体、<i>或<em>斜体 1.定义 粗体、斜体的实现可以在CSS中实现&…

【半结构化访谈法】

文章目录 什么是半结构化访谈法&#xff1f;如何进行半结构化访谈&#xff1f;1. 确定研究目的和主题2. 制定访谈指南3. 进行访谈4. 记录和分析数据5. 报告结果 半结构化访谈法的优缺点优点&#xff1a;缺点&#xff1a; 什么是半结构化访谈法&#xff1f; 半结构化访谈法是一…

Windows 和 Linux 的免费媒体播放器 - SMPlayer

Windows 和 Linux 的免费媒体播放器 - SMPlayer 1. A quick look at SMPlayer2. Downloads2.1. Packages for Ubuntu References https://www.smplayer.info/ 1. A quick look at SMPlayer SMPlayer is a free media player for Windows and Linux with built-in codecs that…

【MySQL】事务日志

事务的隔离性由锁机制实现&#xff0c;事务的原子性、一致性和持久性由redo日志和undo日志实现。 一、redo日志 1.1、为什么需要redo日志 一方面&#xff0c;由于数据从内存写回磁盘需要一定的时间&#xff0c;假如在事务提交后&#xff0c;还没有写回磁盘&#xff0c;数据库…

优雅地处理前端数据转换:自定义封装 translateDict 函数

在前端开发中&#xff0c;我们经常需要处理数据的转换。有时候&#xff0c;我们需要将某种格式的数据转换为另一种格式&#xff0c;这可能涉及到字符串、数组等不同数据类型的转换。在这篇博客中&#xff0c;我们将介绍一个名为 translateDict 的函数&#xff0c;它可以帮助我们…

Rancher(v2.6.3)——Rancher部署Nginx(单机版)

Rancher部署Nginx详细说明文档&#xff1a;https://gitee.com/WilliamWangmy/snail-knowledge/blob/master/Rancher/Rancher%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3.md#5rancher%E9%83%A8%E7%BD%B2nacos ps&#xff1a;如果觉得作者写的还行&#xff0c;能够满足您的需求&#x…

LeetCode225:用队列实现栈

题目描述 请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0c;并支持普通栈的全部四种操作&#xff08;push、top、pop 和 empty&#xff09;。 实现 MyStack 类&#xff1a; void push(int x) 将元素 x 压入栈顶。 int pop() 移除并返回栈顶元…

web前端面试题---->HTML、CSS

一.居中方法 block元素如何居中 margin&#xff1a;0 auto&#xff1b;position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);flex布局&#xff1a; 对父元素操作 &#xff1a; justify-content:center; al…

商城小程序项目实现监控的可观测性最佳实践

前言 微信小程序是一种轻量级的应用程序&#xff0c;用户可以在微信内直接使用&#xff0c;无需下载安装。它具有独立的开发框架和生态系统&#xff0c;支持丰富的功能和交互&#xff0c;包括社交、购物、服务等。 观测云对微信小程序的监控能够实时收集性能指标、错误日志和…

深入理解 C++ 中的 IO 流【iostream篇】

C 中的输入输出流&#xff08;iostream&#xff09;是非常重要的一部分&#xff0c;它们提供了与用户交互以及与文件系统进行数据交换的功能。本文将深入探讨 C 中的 cin 和 cout&#xff0c;介绍它们的使用方法、缓冲区以及常用的成员函数等相关知识。 1. cin 和 cout 的基本…