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

链表理论基础

  • 链表是一种通过指针串连在一起的线性结构,每一个节点由两部分组成,一个是数据域,一个是指针域(存放指向下一个节点的指针)。最后一个节点的指针指向 null。
  • 链表的存储方式:数组在内存中是连续存储的,但链表不是连续存储的,各个节点分布在内存的不同地址空间中,用指针串联在一起。
  • 链表的定义:
// 单链表
struct ListNode{int val;  // 节点上存储的值ListNode *next;  // 指向下一个节点的指针ListNode(int x) : val(x), next(NULL) {}  // 链表节点的构造函数
};

C++ 也默认生成了一个构造函数,但这个构造函数不会初始化任何成员变量
我们自己的构造函数初始化链表节点:ListNode* head = new ListNode(5);
使用默认的构造函数初始化:ListNode* head = new ListNode(); head->val = 5;

  • 删除或增加节点:这个操作与其他节点是无关的,时间复杂度为 O(1)。但是在指定位置操作,还需要有查询操作。另外注意删除节点时只是改变指针指向,删除的节点仍在内存中,最好去主动释放。
  • 查找:链表只能从一端开始遍历,因此时间复杂度为 O(n)。
  • 性能分析:数组固定长度,连续存储,在删除或插入元素时,需要逐个移动元素,时间复杂度 O(n),但查找方便,时间复杂度 O(1)。链表长度并不固定,不连续存储,增删元素时间复杂度为 O(1),但查找 O(n)。
    因此数组适用于数据量固定,查找频繁,较少增删;链表适用于数据量不固定,增删频繁,较少查找的情景。

移除链表元素

Alt
之前我们做过一道移除链表元素的题,其难点在于数组连续存储,所以移除元素之后还需要移动其他元素保证连续。但是链表不需要保证连续存储,移除操作与其他元素无关的,其实我们直接遍历整条链表就可以了。
处理过程需要注意的问题:头节点与其他节点不同的处理办法。其他节点都是改变前一个节点的指针指向,但删除头节点的话需要不断向后更新头节点。可以添加一个虚拟节点 dummy 使得头节点的处理一般化

class Solution{
public:ListNode* removeElements(ListNode* head, int val){ListNode* dummy = new ListNode();dummy->next = head;ListNode* cur = dummy;while(cur->next != NULL){  // 用cur->next进行判断,注意删除节点释放内存的操作if(cur->next->val == val){ListNode* tmp = cur->next;cur->next = cur->next->next;delete tmp;}else  cur = cur->next;}head = dummy->next;delete dummy;return head;}
};

设计链表

Alt
注意C++语法。public 和 private 的前后顺序。维护一个虚拟节点和节点数目会使其他操作更加方便。

class MyLinkedList{
public:struct ListNode{int val;ListNode* next;ListNode(int val) : val(val), next(NULL) {}};MyLinkedList(){_dummyHead = new ListNode(0);_size = 0;}int get(int index){if(index < 0 || index > _size - 1)  return -1;ListNode* cur = _dummyHead->next;while(index--){cur = cur->next;}return cur->val;}void addAtHead(int val){ListNode* node = new ListNode(val);ListNode* cur = _dummyHead;node->next = _dummyHead->next;_dummyHead->next = node;_size++;}void addAtTail(int val){ListNode* node = new ListNode(val);ListNode* cur = _dummyHead;while(cur->next){cur = cur->next;}cur->next = node;_size++;}void addAtIndex(int index, int val){if(index < 0 || index > _size)  return;ListNode* node = new ListNode(val);ListNode* cur = _dummyHead;while(index--){cur = cur->next;}node->next = cur->next;cur->next = node;_size++;}void deleteAtIndex(int index){if(index < 0 || index > _size - 1)  return;ListNode* cur = _dummyHead;while(index--){cur = cur->next;}cur->next = cur->next->next;_size--;}
private:int _size;  // 记录链表中的节点数目ListNode* _dummyHead;  // 设计一个虚拟节点,解决头节点的问题
};

反转链表

Alt
链表只能头节点开始遍历,为了避免新建链表,可以选择使用双指针法。一个指针指向前一个节点,一个指针指向当前节点。注意:在遍历过程中会改变 next 指针的指向,所以要使用中间变量来记录下一个节点,再改变当前节点的 next 指针指向。

class Solution{
public:ListNode* reverseList(ListNode* head){if(!head)  return head;ListNode* cur = head;ListNode* pre = NULL;while(cur){ListNode* tmp = cur->next;  // 记录当前节点的下一个cur->next = pre;  // 翻转当前节点的指向pre = cur;  // 向后遍历cur = tmp;}return pre;}
};

递归法,上面的迭代法可以改写成递归。

class Solution{
public:ListNode* reverse(ListNode* pre, ListNode* cur){if(!cur)  return pre;ListNode* tmp = cur->next;cur->next = pre;return reverse(cur, tmp);}ListNode* reverseList(ListNode* head){return reverse(NULL, head);}
};

还有另一种比较难以想到的方法,是从后往前翻转。

class Solution{
public:ListNode* reverseList(ListNode* head){if(head == NULL)  return head;if(head->next == NULL)  return head;ListNode* last = reverseList(head->next);  // 把原链表末尾的节点返回(翻转后的头节点)head->next->next = head;  // 将head节点移到队列尾部,注意这一步没有改变原链表中指向head的指针,使得每层递归都能将当前head移动到队尾head->next = NULL;  // head移到队尾,指向空节点return last;}
};

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

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

相关文章

【C++干货基地】namespace超越C语言的独特魅力(文末送书)

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引入 哈喽各位铁汁们好啊&#xff0c;我是博主鸽芷咕《C干货基地》是由我的襄阳家乡零食基地有感而发&#xff0c;不知道各位的…

PDshell16逆向PostgreSQL 工程显示字段comment备注

现状&#xff1a;当刚逆向成功的表结构是没有原来表结构中的&#xff0c;comment备注如下 然后pd逆向工程的sql已经返回了这个备注的含义 解决方案&#xff1a; 1、设置显示注释列 tools——Display Preferences…如下 勾选-按照下面得方式勾选这三个 复制这里的VBS脚本&a…

Java 基础面试题 String(二)

Java 基础面试题 String&#xff08;二&#xff09; 文章目录 Java 基础面试题 String&#xff08;二&#xff09;String#equals() 和 Object#equals() 有何区别&#xff1f;字符串常量池的作用了解吗&#xff1f;String s1 new String("abc");这句话创建了几个字符…

医学图像的图像处理、分割、分类和定位-1

一、说明 本报告全面探讨了应用于医学图像的图像处理和分类技术。开展了四项不同的任务来展示这些方法的多功能性和有效性。任务 1 涉及读取、写入和显示 PNG、JPG 和 DICOM 图像。任务 2 涉及基于定向变化的多类图像分类。此外&#xff0c;我们在任务 3 中包括了胸部 X 光图像…

响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 例4-7 datalist

代码 <!doctype html> <html> <head> <meta charset"utf-8"> <title>datalist</title> </head><body> <input id"address" list"addressList"> <datalist id"addressList"…

Kafka-多线程消费及分区设置

目录 一、Kafka是什么&#xff1f;消息系统&#xff1a;Publish/subscribe&#xff08;发布/订阅者&#xff09;模式相关术语 二、初步使用1.yml文件配置2.生产者类3.消费者类4.发送消息 三、减少分区数量1.停止业务服务进程2.停止kafka服务进程3.重新启动kafka服务4.重新启动业…

第十七期长江沙龙:“大海遗子”——秦岭细鳞鲑

洄游是生命延续的本能&#xff0c;有这样一种鱼&#xff0c;本该是大海孕育的孩子&#xff0c;却从海洋中洄游到淡水中&#xff0c;它们充分利用其惊人的跳跃能力&#xff0c;逐渐演变成为了山溪中的“精灵”&#xff0c;向世界充分展示了它们奋勇向上的拼搏精神。 1月20日&am…

【数据结构与算法】归并排序详解:归并排序算法,归并排序非递归实现

一、归并排序 归并排序是一种经典的排序算法&#xff0c;它使用了分治法的思想。下面是归并排序的算法思想&#xff1a; 递归地将数组划分成较小的子数组&#xff0c;直到每个子数组的长度为1或者0。将相邻的子数组合并&#xff0c;形成更大的已排序的数组&#xff0c;直到最…

2024年回炉计划之排序算法(一)

算法是计算机科学和信息技术中的重要领域&#xff0c;涉及到问题求解和数据处理的方法。要学习算法&#xff0c;你可能需要掌握以下一些基本知识&#xff1a; 基本数据结构&#xff1a; 了解和熟练使用各种数据结构&#xff0c;如数组、链表、栈、队列、树和图等。数据结构是算…

ESP32-TCP服务端(Arduino)

将ESP32设置为TCP服务器 介绍 TCP&#xff08;Transmission Control Protocol&#xff09;传输控制协议&#xff0c;是一种面向连接的&#xff08;一个客户端对应一个服务端&#xff09;、可靠的传输层协议。在TCP的工作原理中&#xff0c;它会将消息或文件分解为更小的片段&a…

[小程序]页面事件

一、下拉刷新 1.开启和配置 小程序中开启下拉刷新的方式有两种&#xff1a; ①全局开启下来刷新 在app.json的window节点中&#xff0c;设置enablePullDownRefresh设为ture。 ②局部开启下来刷新 在页面对应的json文件的的window节点中&#xff0c;设置enablePullDownRefresh设…

[Unity] Tilemap瓦片左右翻转(上下翻转)

Tile&#xff08;瓦片&#xff09;左右翻转感觉是很常用的一个功能啊&#xff01;看了一些教程都没有提及&#xff0c;心想难道要把每张Sprite再做一张对称的、再做成瓦片吗&#xff1f; 图片量x2 、瓦片量x2、不现实&#xff01;一定有方法&#xff01; 搜索了了半天没找到方…

Windows WSL2 占用磁盘空间清理释放

目前工作中时常用到WSL2&#xff08;Ubuntu20.04&#xff09;&#xff0c;在使用一段时间后会发现WSL2所占用磁盘空间越来越多&#xff0c;体现在WSL2之上安装Linux分发对应的vhdx虚拟磁盘文件体积越来越大&#xff0c;会占用Windows自身空间&#xff0c;即使手动清理了Linux分…

【JavaEE】文件操作与IO

作者主页&#xff1a;paper jie_博客 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文于《JavaEE》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造的。笔者用重金(时间和精力)打造&…

【QT+QGIS跨平台编译】之三:【OpenSSL+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文章目录 一、OpenSSL介绍二、OpenSSL配置三、Window环境下配置四、Linux环境下配置五、Mac环境下配置 一、OpenSSL介绍 OpenSSL是一个开放源代码的软件库包&#xff0c;应用程序可以使用这个包来进行安全通信&#xff0c;避免窃听&#xff0c;同时确认另一端连接者的身份。这…

使用Element中的input组件如何实现文字和输入框在一行显示

利用 <el-form-item label"商品名称&#xff1a;">标签包裹即可&#xff0c;label写提示文字 <el-form ref"form" label-width"100px"><el-form-item label"商品名称&#xff1a;"><el-input v-model"na…

免费的WordPress插件大全

在当今数字化的时代&#xff0c;拥有一个强大的在线存在变得至关重要。而对于使用WordPress建站的用户来说&#xff0c;插件是提高网站功能的关键。在这篇文章中&#xff0c;我们将为您推荐三款免费的WordPress插件&#xff0c;它们不仅是147SEO软件中的佼佼者&#xff0c;而且…

Django(九)

1. 用户登录-Cookie和Session 什么是cookie和session&#xff1f; 发送HTTP请求或者HTTPS请求(无状态&短连接) http://127.0.0.1:8000/admin/list/ https://127.0.0.1:8000/admin/list/http无状态短连接&#xff1a;一次请求响应之后断开连接&#xff0c;再发请求重新连…

华南理工大学数字信号处理实验实验二源码(薛y老师)

一、实验目的 ▪ 综合运用数字信号处理的理论知识进行信号分析并利用MATLAB作为编程工具进行计算机实现&#xff0c;从而加 深对所学知识的理解&#xff0c;建立概念。 ▪ 掌握数字信号处理的基本概念、基本理论和基本方法。 ▪ 学会用MATLAB对信号进行分析和处理。 ▪ 用F…

基于springboot+vue的旅游网站系统(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…