C++数据结构与算法——链表

C++第二阶段——数据结构和算法,之前学过一点点数据结构,当时是基于Python来学习的,现在基于C++查漏补缺,尤其是树的部分。这一部分计划一个月,主要利用代码随想录来学习,刷题使用力扣网站,不定时更新,欢迎关注!

文章目录

  • 一、移除链表元素(力扣203)
  • 二、设计链表(力扣707)
  • 三、翻转链表(力扣206)
  • 四、两两交换链表中的节点 (力扣24)
  • 五、删除链表的倒数第 N 个结点(力扣19)
  • 六、链表相交(力扣面试题02.07链表相交)
  • 七、环形链表Ⅱ(力扣142)

一、移除链表元素(力扣203)

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点
在这里插入图片描述
头结点单独处理

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* removeElements(ListNode* head, int val) {// 先判断头结点是不是val,如果是的话,head就后移while(head!=NULL && head->val==val){ListNode * temp ;temp = head;head = head->next;delete temp;}// 定义一个指针指向中间过程的结点ListNode * cur = head;while(cur!=NULL&&cur->next!=NULL){if(cur->next->val==val){// 删除下一个结点ListNode *temp = cur->next;cur->next = cur->next->next;delete temp;}else{cur = cur->next;}}return head;}
};

在这里插入图片描述

虚拟头节点

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* removeElements(ListNode* head, int val) {// 定义一个虚拟头结点ListNode * dummyHead = new ListNode(0); dummyHead->next = head;// 定义一个遍历结点ListNode *cur = dummyHead;while(cur!=NULL&&cur->next!=NULL){if(cur->next->val==val){ListNode * temp = cur->next;cur->next = cur->next->next;delete temp;}else{cur = cur->next;}}return dummyHead->next;}
};

在这里插入图片描述

二、设计链表(力扣707)

你可以选择使用单链表或者双链表,设计并实现自己的链表。
单链表中的节点应该具备两个属性:val 和 next 。val 是当前节点的值,next 是指向下一个节点的指针/引用。
如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。
实现 MyLinkedList 类:
MyLinkedList() 初始化 MyLinkedList 对象。
int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。
void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。
void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为 index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。
void deleteAtIndex(int index) 如果下标有效,则删除链表中下标为 index 的节点。
示例:
输入
[“MyLinkedList”, “addAtHead”, “addAtTail”, “addAtIndex”, “get”, “deleteAtIndex”, “get”]
[[], [1], [3], [1, 2], [1], [1], [1]]
输出
[null, null, null, null, 2, null, 3]
解释
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.addAtHead(1);
myLinkedList.addAtTail(3);
myLinkedList.addAtIndex(1, 2); // 链表变为 1->2->3
myLinkedList.get(1); // 返回 2
myLinkedList.deleteAtIndex(1); // 现在,链表变为 1->3
myLinkedList.get(1); // 返回 3
提示:
0 <= index, val <= 1000
请不要使用内置的 LinkedList 库。
调用 get、addAtHead、addAtTail、addAtIndex 和 deleteAtIndex 的次数不超过 2000 。

// 创建一个结点
class LinkNode{
public:LinkNode(int inputVal){this->val = inputVal;}int val;LinkNode *next=NULL;
};class MyLinkedList {
public:// 实现一个单链表MyLinkedList() {dummyHead= new LinkNode(0);size=0; // 获取链表长度}int get(int index) {if(index<0||index>(this->size-1)){return -1;}LinkNode * cur = dummyHead->next;while(index--){cur = cur->next;}return cur->val;}void addAtHead(int val) {LinkNode * insertNode = new LinkNode(val);insertNode->next = dummyHead->next;dummyHead->next =insertNode;size++;}void addAtTail(int val) {// 找到尾部LinkNode * cur = dummyHead;while(cur!=NULL&&cur->next!=NULL){cur = cur->next;}// 插入LinkNode * insertNode = new LinkNode(val);cur->next = insertNode;insertNode->next = NULL;size++;}void addAtIndex(int index, int val) {if(index>=this->size+1){showLink();return;}else if(index == this->size){addAtTail(val);return;}else if(index<=0){addAtHead(val);return;}LinkNode * cur = dummyHead;while(index--){cur = cur->next;}// 添加LinkNode * insertNode = new LinkNode(val);insertNode->next = cur->next;cur->next = insertNode;size++;}void deleteAtIndex(int index) {if(index<0||index>(this->size-1)){return ;}LinkNode * cur = dummyHead;while(index--){cur = cur->next;}// 删除LinkNode * temp = cur->next;cur->next = cur->next->next;delete temp;temp = NULL;size--;}LinkNode * dummyHead= new LinkNode(0);int size=0; // 获取链表长度void showLink(){LinkNode * cur = dummyHead;while(cur!=NULL&&cur->next!=NULL){cout<<cur->next->val<<" ";cur = cur->next;}cout<<endl;}
};// 6,7,2,0,4,
// 4/*** Your MyLinkedList object will be instantiated and called as such:* MyLinkedList* obj = new MyLinkedList();* int param_1 = obj->get(index);* obj->addAtHead(val);* obj->addAtTail(val);* obj->addAtIndex(index,val);* obj->deleteAtIndex(index);*/

三、翻转链表(力扣206)

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
在这里插入图片描述

双指针,注意先移动pre再移动cur。

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* reverseList(ListNode* head) {if(head==NULL||head->next==NULL){// 只有一个结点return head;}// 定义两个指针,一个指前面的,一指后面的ListNode *pre = NULL;ListNode *cur = head;while(cur!=NULL){// 用一个值去接收curListNode *temp = cur->next;cur->next = pre;pre = cur;cur = temp;}return pre;}};

在这里插入图片描述
另外一种通过递归的方式反转链表,等学到递归再补上

四、两两交换链表中的节点 (力扣24)

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
在这里插入图片描述

每两个交换一次,需要找到交换之前的节点。注意交换实的逻辑,对于不变量需要提前保存信息。

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* swapPairs(ListNode* head) {if(head==NULL||head->next==NULL){return head;}// 创建一个虚拟头结点ListNode * dummyNode = new ListNode(0);dummyNode->next =head;ListNode * cur = dummyNode;while(cur->next!=NULL&&cur->next->next!=NULL){ListNode * a = cur->next;ListNode * b= cur->next->next->next;cur->next = cur->next->next;cur->next->next = a;a->next = b;cur = cur->next->next;}return dummyNode->next;}
};

在这里插入图片描述

五、删除链表的倒数第 N 个结点(力扣19)

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
在这里插入图片描述

双指针的经典题目,快指针先走n个,快慢指针再同时走,当快指针下一个为NULL时,慢指针下一个即为要删除的元素

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {
public:ListNode* removeNthFromEnd(ListNode* head, int n) {if (head==NULL){return head;}ListNode * dummyNode = new ListNode(0);dummyNode->next = head;// 使用快慢指针ListNode* fast = dummyNode;ListNode* slow = dummyNode;while(n--){// 快指针先走n个fast = fast->next;}while(fast!=NULL&&fast->next!=NULL){fast = fast->next;slow = slow->next;}// 删除元素ListNode * temp = slow->next;slow->next = slow->next->next;delete temp; // 删除return dummyNode->next;}
};

在这里插入图片描述

六、链表相交(力扣面试题02.07链表相交)

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
在这里插入图片描述

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {// 实际上是找相等的结点,不是值相等,而是 是同一个结点// 将两个链表右对齐// 求两个链表的长度if(headA==NULL||headB==NULL){return NULL;}int lenA =1;int lenB =1;ListNode * curA = headA;ListNode * curB = headB;while(curA->next!=NULL){lenA++;curA = curA->next;}while(curB->next!=NULL){lenB++;curB = curB->next;}// 找最短的链表int minLen =min(lenA,lenB);// AB需要移动的长度int needA= lenA-minLen;int needB = lenB - minLen;// 右对齐两个节点while(needA--){headA = headA->next;}while(needB--){headB = headB->next;}// 比较之后的链表是否相同while(headA!=NULL||headB!=NULL){if(headA== headB){return headA;}else{headA = headA->next;headB = headB ->next;}}return NULL;}
};

七、环形链表Ⅱ(力扣142)

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
在这里插入图片描述

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode *detectCycle(ListNode *head) {// 用一个map记录访问过的地址,不断将地址放入map,如果某次map的长度没有发生变化,说明入环了map<ListNode *,ListNode *> addmap;if(head==NULL){return NULL;}// 创建虚拟头结点ListNode * dummyHead = new ListNode(0);dummyHead->next = head;// 遍历ListNode * cur = dummyHead;while(cur!=NULL){// 记录之前的sizeint firstSize = addmap.size();addmap.insert(make_pair(cur->next,cur->next));int endSize = addmap.size();if(endSize==firstSize){// 没有发生变化,说明已经入环return addmap[cur->next];}else{cur = cur->next;}}return NULL;}
};

在这里插入图片描述
使用map存储每个结点的next,如果map存完之后长度没有变,那么说明进入环了,map中存储的值即为要返回的索引值。
使用双指针

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {
public:ListNode *detectCycle(ListNode *head) {ListNode * first = head;ListNode * slow = head;while(first!=NULL&&first->next!=NULL){first = first->next->next;slow = slow->next;if(first==slow){// 此时相遇ListNode * index1 = first;ListNode * index2 = head;// 找入环口while(index1!=index2){index1 = index1->next;index2 = index2->next;}return index1;}}return NULL;}
};

在这里插入图片描述

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

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

相关文章

Linux初始相关配置

前言 在学完了Linux的相关基础命令后&#xff0c;在正式使用Linux系统之前&#xff0c;我觉得配置一些东西是很有意义的。 文章目录 前言1.权限配置&#xff0c;普通用户无法sudo提权2.vim配置3.vim其他操作4.动静态库5.gcc/g6.程序翻译的过程7.make/makefile8.cmake/CMakeLis…

【Unity3D小功能】Unity3D中设置Text行首不出现标点符号

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 在开发中会遇到Text的文本内容行首出现标点符号的情况&#xf…

《动手学深度学习(PyTorch版)》笔记4.8

注&#xff1a;书中对代码的讲解并不详细&#xff0c;本文对很多细节做了详细注释。另外&#xff0c;书上的源代码是在Jupyter Notebook上运行的&#xff0c;较为分散&#xff0c;本文将代码集中起来&#xff0c;并加以完善&#xff0c;全部用vscode在python 3.9.18下测试通过。…

实战教程:使用Spring Boot和Vue.js开发社区团购管理系统

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

使用AnimeGAN2将照片动漫化--入门

使用AnimeGAN2将照片动漫化--入门 1. 环境准备2. 使用3. 总结 1. 环境准备 首先下载AnimeGAN2:https://github.com/TachibanaYoshino/AnimeGANv2.git 然后使用conda 创建一个python3.6的环境conda create -n pyt36 python3.6&#xff1a; 创建一个requirements.txt文件&am…

生信学院|02月02日《云端设计一体化平台—3DEXPERIENCE》

课程主题&#xff1a;云端设计一体化平台—3DEXPERIENCE 课程时间&#xff1a;2024年02月02日 14:00-14:30 主讲人&#xff1a;郭俊辰 生信科技 解决方案顾问 1、云产品发展趋势 2、3DExperience产品的介绍 3、3DExperience DEMO演示 请安装腾讯会议客户端或APP&#xff…

记一次无法ping通Cisco switch处理

网络小白&#xff0c;仅仅在工作中需要telnet到switch。奈何之前不知什么原因一直无法ping通该switch&#xff0c;很久只能使用串口连接来配置了。而今遇到了使用脚本telnet switch的场景&#xff0c;不得不再次面对这个问题。 首先还是使用串口来看switch是否拿到ip&#xff…

【蓝桥杯冲冲冲】进阶搜索 Anya and Cubes

蓝桥杯备赛 | 洛谷做题打卡day22 文章目录 蓝桥杯备赛 | 洛谷做题打卡day22Anya and Cubes题面翻译输入格式输出题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 样例 #3样例输入 #3样例输出 #3 提示题解代码我的一些话 Anya and Cubes …

LeetCode 54 螺旋矩阵

题目描述 螺旋矩阵 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5]示例 2&#xff1a; 输入&#x…

线程池的知识

线程池是由服务器预先创建的一组子线程&#xff0c;线程池中的线程数量应该和 CPU 数量差不多。线程池中的所 有子线程都运行着相同的代码。当有新的任务到来时&#xff0c;主线程将通过某种方式选择线程池中的某一个子 线程来为之服务。相比与动态的创建子线程&#xff0c;选…

【昕宝爸爸小模块】深入浅出详解之常见的语法糖

深入浅出详解之常见的语法糖 一、&#x1f7e2;关于语法糖的典型解析二、&#x1f7e2;如何解语法糖&#xff1f;2.1&#x1f7e2;糖块一、switch 支持 String 与枚举2.2&#x1f4d9;糖块二、泛型2.3&#x1f4dd;糖块三、自动装箱与拆箱2.4&#x1f341;糖块四、方法变长参数…

实战Vue.js与MySQL:爱心商城项目开发指南

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

【深入浅出SpringCloud原理及实战】「Netflix系列之Hystrix」针对于限流熔断组件Hystrix的回退降级实现方案和机制

针对于限流熔断组件Hystrix的回退降级实现方案和机制 依赖隔离依赖隔离之线程&线程池高延迟请求的例子 线程池的优势线程池的弊端线程池的开销线程池开销 信号量 依赖隔离 Hystrix通过使用『舱壁模式』&#xff08;注&#xff1a;将船的底部划分成一个个的舱室&#xff0c;…

SpringBoot+BCrypt算法加密

BCrypt是一种密码哈希函数,BCrypt算法使用“盐”来加密密码,这是一种随机生成的字符串,可以在密码加密过程中使用,以确保每次加密结果都不同。盐的使用增强了安全性,因为攻击者需要花费更多的时间来破解密码。 下图为使用BCrypt算法后的的密码结果值: 下面讲一下注册登陆…

[设计模式Java实现附plantuml源码~结构型]不兼容结构的协调——适配器模式

前言&#xff1a; 为什么之前写过Golang 版的设计模式&#xff0c;还在重新写Java 版&#xff1f; 答&#xff1a;因为对于我而言&#xff0c;当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言&#xff0c;更适合用于学习设计模式。 为什么类图要附上uml 因为很…

AIGC专题:生成式AI(GenAI)赋能供应链之路

今天分享的是AIGC系列深度研究报告&#xff1a;《AIGC专题&#xff1a;生成式AI&#xff08;GenAI&#xff09;赋能供应链之路》。 &#xff08;报告出品方&#xff1a;Gartner&#xff09; 报告共计&#xff1a;46页 什么是生成式人工智能 ChatGPT&#xff1a;一种OpenAI服…

Mac删除自带的ABC输入法,简单快捷

一、下载PlistEdit Pro软件 二、终端执行 sudo open ~/Library/Preferences/com.apple.HIToolbox.plist 三、其中有一个数字下面的KeyboardLayout Name的value为“ABC”&#xff0c;这就是ABC输入法&#xff0c;点击上面的Delete按钮&#xff0c;删除整项ABC内容&#xff0c…

MySQL表的基本操作

目录 一、创建表的语法 二、表的物理存储类型 三、数据类型 3.1 文本类型类型&#xff1a; 3.2 数字类型&#xff1a; 3.3 时间\日期类型&#xff1a; 常用数据类型&#xff1a; 四、查看表 五、删除表 六、修改表的结构 八、数据库字典 九、表的约束 9.1 五类完整…

Unity 常见的图像压缩格式优缺点

在Unity中&#xff0c;将图像压缩至更小的大小&#xff0c;既可以加快加载速度&#xff0c;也可以减少内存的占用。根据不同的目标平台&#xff0c;Unity提供了以下几种常见的图像压缩格式&#xff1a; 1. RGBA Compressed: 是一种通过压缩的方式来存储RGBA&#xff08;红色、…

中国的茶文化:现代生活中的茶文化

中国的茶文化&#xff1a;现代生活中的茶文化 引言 在现代社会的快节奏生活中&#xff0c;茶文化并未随时间流逝而褪色&#xff0c;反而以其独特的方式融入了全球各地人们的日常生活。它超越了饮品本身的范畴&#xff0c;成为一种连接历史、人文与现代生活方式的艺术形式。本文…