数据结构之链表练习与习题详细解析
个人主页:点我进入主页
专栏分类:C语言初阶 C语言程序设计————KTV C语言小游戏 C语言进阶
C语言刷题 数据结构初阶
欢迎大家点赞,评论,收藏。
一起努力,一起奔赴大厂。
目录
1.前言
2.习题解析
2.1习题一
2.2习题二
2.3习题三
2.4习题四
2.5习题五
3.总结
1.前言
在上次的文章中我们对一些练习的题目进行解析 ,链表是对于数据结构的基础,对我们的后面的内容非常重要,这次我们对于牛客网和力扣的部分题目进行练习 ,这次的题目相对于上次的习题有一些强度,我们可以先自己练习练习让后再看后面的解析
习题一:链表的回文结构
习题二:输入两个链表,找出它们的第一个公共结点
习题三:给定一个链表,判断链表中是否有环
习题四:给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 NULL
习题五:给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。要求返回这个链表的深度拷贝
2.习题解析
2.1习题一
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。
测试样例:
1->2->2->1返回 true
class PalindromeList {public:bool chkPalindrome(ListNode* head) {// write code herestruct ListNode* phead = (ListNode*)malloc(sizeof(ListNode));struct ListNode* s = phead, *s1 = head;struct ListNode *tail;phead->next = NULL;struct ListNode* slow = head;struct ListNode* fast = head;while (fast && fast->next) {slow = slow->next;fast = fast->next->next;}while (slow) { tail=slow->next;slow->next = s->next;s->next = slow;slow = tail;}s = s->next;while (s&&s1) {if (s->val != s1->val)return false;s = s->next;s1 = s1->next;}return true;}
};
在这里我们可以用到快慢指针,我们可以对几种情况进行判断,空链表,单个节点,奇数个节点的链表,偶数个节点的链表这几种情况,我们可以创建一个头节点进行解题,我们先看奇数个几点的链表和偶数个节点的链表,例如5个或6个节点

我们让慢指针每次走一次,快指针每次走两次

当慢指针在中间的位置时当有奇数个节点时fast->next为NULL,偶数个节点时fast为NULL ,因此我们想要找到中间节点可以利用while循环来找到中间节点,找到中间节点后我们需要对数据进行比对来判断是不是回文结构如果是回文结构数据就是逆置的,因此我们可以想到对链表进行逆置,我们知道头插会将数据逆置,因此我们可以利用头插将数据进行逆置,我们创建一个头节点用于链表的逆置,逆置完成后我们进行数据的比对,当有一个节点时

我们看到当找中间节点时由于fast->next为NULL,会直接停止,空链表和这个相同,这俩不用格外考虑。
2.2习题二
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
图示两个链表在节点 c1 开始相交:

题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
自定义评测:
评测系统 的输入如下(你设计的程序 不适用 此输入):
intersectVal- 相交的起始节点的值。如果不存在相交节点,这一值为0listA- 第一个链表listB- 第二个链表skipA- 在listA中(从头节点开始)跳到交叉节点的节点数skipB- 在listB中(从头节点开始)跳到交叉节点的节点数
评测系统将根据这些输入创建链式数据结构,并将两个头节点 headA 和 headB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。
示例 1:

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
— 请注意相交节点的值不为 1,因为在链表 A 和链表 B 之中值为 1 的节点 (A 中第二个节点和 B 中第三个节点) 是不同的节点。换句话说,它们在内存中指向两个不同的位置,而链表 A 和链表 B 中值为 8 的节点 (A 中第三个节点,B 中第四个节点) 在内存中指向相同的位置。
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {struct ListNode*list1=headA,*list2=headB;int counta=0,countb=0;while(list1){counta++;list1=list1->next;}while(list2){countb++;list2=list2->next;}int def=abs(counta-countb);struct listNode*longList=headA,*slowList=headB;if(counta<countb){longList=headB;slowList=headA;}list1=longList;list2=slowList;while(def--){list1=list1->next;}while(list1&&list2&&(list1!=list2)){list1=list1->next;list2=list2->next;}if(list1==NULL||list2==NULL)return NULL;else return list1;}
我们可以先得到链表A的长度和链表B的长度,然后找到两个链表节点的差值,然后让长的链表先走差值个节点,然后让两个指针分别指向两个链表,我们用到一个非常好的方法,我们假设长的先指向A,短的指向B,然后比较A的节点数和B的节点数,然后进行修正,然后对长的指针和短的指针进行操作即可,让他们同时走,比较这两个指针的地址(必须是地址),当相同且不为NULL时返回。
2.3习题三
给你一个链表的头节点 head ,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
如果链表中存在环 ,则返回 true 。 否则,返回 false 。
示例 1:

输入:head = [3,2,0,-4], pos = 1 输出:true 解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:

输入:head = [1,2], pos = 0 输出:true 解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:

输入:head = [1], pos = -1 输出:false 解释:链表中没有环。
bool hasCycle(struct ListNode *head) {struct ListNode*fast=head,*slow=head;if(fast==NULL||fast->next==NULL){return false;}slow=slow->next;fast=fast->next->next;while(slow!=fast){if(fast==NULL||fast->next==NULL){return false;}slow=slow->next;fast=fast->next->next;}return true;
}
在这里我们可以想到主要有两种情况的链表

分别为环长和环短的两种,我们可以搞快慢指针进行操作,快指针每次走两次,慢指针每次走一次,

当慢指针指向环的开始时由于快指针每次走两次,满指针每次走一次,我们看快指针相对于慢指针每次走一次,那么 快指针一定会和慢指针相遇,那么我们先进行判断是不是空,然后快慢指针进行走,然后进行循环,进行判断,对于快慢指针的走法我们想到快指针走三次,慢指针走一次能不能成功,快指针每次走m次,慢指针每次走n次是否可以,我们先对于快指针走三次,慢指针走一次,慢指针走到环的开始位置,当快指针和慢指针差奇数个时第二次相遇可以,当差偶数个时此一次相遇即可,当快指针每次走m次,慢指针每次走n次时

我们设环外为L,环长为C,slow和fast的差距为x,我们可以得到公式:m(L+x)=n(L+kC+X),我们可以化简为(m-n)L=kLC+(n-m)X,L=kLC/(m-n)-X;我们根据公式可以得到需要满足m>n才有可能相遇。
2.4习题四
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。

输入:head = [3,2,0,-4], pos = 1 输出:返回索引为 1 的链表节点 解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:

输入:head = [1,2], pos = 0 输出:返回索引为 0 的链表节点 解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:

输入:head = [1], pos = -1 输出:返回 null 解释:链表中没有环。
struct ListNode *detectCycle(struct ListNode *head) {struct ListNode *slow=head;struct ListNode *fast=head;if(fast==NULL||fast->next==NULL)return NULL;slow=slow->next;fast=fast->next->next;while(slow!=fast){if(fast==NULL||fast->next==NULL)return NULL;slow=slow->next;fast=fast->next->next;}slow=head;while(slow!=fast){slow=slow->next;fast=fast->next;}return fast;
}
根据上面一道题目我们可以来判断有没有环,我们还得到一个公式 ,L=kC/(m-n)-X;我们先看快指针走两次,慢指针走一步。2(L+x)=kC+x+L,L=(k-1)C+C-x,重点就在C-x这里C-x

我们让慢指针指向头节点, 快指针不变,然后让快慢指针每次走1次,(k-1)C是整圈,再走C-x刚好可以和慢指针在环的位置相遇。对于快指针走3次慢指针走1次,3(L+x)=L+kC+x ,L=aC+C-x,和上面相同可以相遇。
2.5习题五
给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。
构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。
例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random --> y 。
返回复制链表的头节点。
用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
val:一个表示Node.val的整数。random_index:随机指针指向的节点索引(范围从0到n-1);如果不指向任何节点,则为null。
你的代码 只 接受原链表的头节点 head 作为传入参数。
示例 1:

输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]] 输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
示例 2:

输入:head = [[1,1],[2,1]] 输出:[[1,1],[2,1]]
示例 3:

输入:head = [[3,null],[3,0],[3,null]] 输出:[[3,null],[3,0],[3,null]]
struct Node* copyRandomList(struct Node* head) {if(head==NULL)return NULL;struct Node*p=head;struct Node*tail=NULL,*phead=NULL;while(p){struct Node*newnode=(struct Node*)malloc(sizeof(struct Node));newnode->val=p->val;newnode->next=NULL;if(tail==NULL){phead=newnode;tail=newnode;}else{tail->next=newnode;tail=tail->next;}p=p->next;}p=head;struct Node*cur=phead;struct Node *prev=phead;while(prev){if(cur){cur=cur->next;}prev->next=p->next;p->next=prev;p=p->next->next;prev=cur;}prev=head;cur=head->next;while(prev){if(prev->random!=NULL)cur->random=prev->random->next;elsecur->random=NULL;prev=cur->next;if(prev)cur=prev->next;}tail=phead;while(tail){if(tail->next)tail->next=tail->next->next;elsetail->next=NULL;tail=tail->next;}return phead;}
我们需要将这个链表进行复制, 对于链表的数据和next指针我们很容易进行复制,但是这个随机指针我们很难,我们第一个想到的是数据进行比较但是由于链表的数据可以重复,我们就不能找到正确的数据,我们可以找到一个很妙的方法,我们先对数据进行数据和指针next的复制,
我们将复制的链表的数据插入到原来的链表中,

这样做是为了对数据进行定位,然后对随机指针进行复制,然后拆下链表重新形成新的链表。
3.总结
今天的内容就结束了,非常欢迎大家来三连,也同时希望大家可以在这篇博客中学到很多东西。
相关文章:
数据结构之链表练习与习题详细解析
个人主页:点我进入主页 专栏分类:C语言初阶 C语言程序设计————KTV C语言小游戏 C语言进阶 C语言刷题 数据结构初阶 欢迎大家点赞,评论,收藏。 一起努力,一起奔赴大厂。 目录 1.前言 2.习题解…...
QT中使用unity
qt把unity发入widget中 头文件showunitywindowsinqt #ifndef SHOWUNITYWINDOWSINQT_H #define SHOWUNITYWINDOWSINQT_H #include <QObject> #include <QProcess> #include <windows.h> #include <winuser.h> #include <QDebug> class ShowUnity…...
QTableView/QTableWidget设置单元格字体颜色及背景色
1.QTableView设置单元格字体颜色及背景色 QStandardItem * pItem new QStandardItem("AAA"); pItem->setBackground(QBrush(Qt::blue)); // 设置背景色 pItem->setForeground(QBrush(Qt::red)); // 设置字体颜色 2.QTableWidget设置单元格字…...
电脑上可以写便签的软件哪些界面比较可爱且好用?
电脑上可以安装使用的便签类软件比较多,在选择使用电脑便签软件时,很多人对便签的外观界面还是比较在意的,一个好看的便签界面在一方面可以引起大家的注意,另一方面可以增加电脑桌面背景和便签类软件的协调性。 电脑便签软件通常…...
2021秋招-总目录
2021秋招-目录 知识点总结 预训练语言模型: Bert家族 1.1 BERT、attention、transformer理解部分 B站讲解–强烈推荐可视化推倒结合代码理解代码部分常见面试考点以及问题: word2vec 、 fasttext 、elmo;BN 、LN、CN、WNNLP中的loss与评价总结 4.1 loss_function࿱…...
HTML5生成二维码
H5生成二维码 前言二维码实现过程页面实现关键点全部源码 前言 本文主要讲解如何通过原生HTML、CSS、Js中的qrcodejs二维码生成库,实现一个输入URL按下回车后输出URL。文章底部有全部源码,需要可以自取。 实现效果图: 上述实现效果为&#…...
大数据-之LibrA数据库系统告警处理(ALM-25005 Nscd服务异常)
告警解释 系统每60秒周期性检测nscd服务的状态,如果连续4次(3分钟)查询不到nscd进程或者无法获取ldapserver中的用户时,产生该告警。 当进程恢复且可以获取ldapserver中的用户时,告警恢复。 告警属性 告警ID 告警级…...
NLP:使用 SciKit Learn 的文本矢量化方法
一、说明 本文是使用所有 SciKit Learns 预处理方法生成文本数字表示的深入解释和教程。对于以下每个矢量化器,将给出一个简短的定义和实际示例:one-hot、count、dict、TfIdf 和哈希矢量化器。 SciKit Learn 是一个用于机器学习项目的广泛库,…...
这些仪表板常用的数据分析模型,你都见过吗?
本文由葡萄城技术团队发布。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。 ##前言 在数字化时代,数据已经成为了企业决策和管理的重要依据。而仪表板作为一种数据可视化工具&#x…...
【Proteus仿真】【Arduino单片机】多功能数字时钟设计
文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真Arduino单片机控制器,使用PCF8574、LCD1602液晶、DS1302温度传感器、DS1302时钟、按键、蜂鸣器等。 主要功能: 系统运行后,LCD1602显示当前日期…...
c语言回文数
以下是用C语言编写的回文数代码: #include <stdio.h>int main() { int num, reversedNum 0, remainder, originalNum; printf("请输入一个正整数:"); scanf("%d", &num); originalNum num; while (num …...
【学习记录】从0开始的Linux学习之旅——编译linux内核
一、学习背景 从接触嵌入式至今,除了安装过双系统接触了一丢丢linux外,linux在我眼中向来是个传说。而如今得到了一块树莓派,于是决心把linux搞起来。 二、概念学习 Linux操作系统通常是基于Linux内核,并结合GNU项目中的工具和应…...
uni-app - 日期 · 时间选择器
目录 1.基本介绍 2.案例介绍 ①注意事项: ②效果展示 3.代码展示 ①view部分 ②js部分 ③css样式 1.基本介绍 从底部弹起的滚动选择器。支持五种选择器,通过mode来区分,分别是普通选择器,多列选择器,时间选择器&a…...
使用USB转JTAG芯片CH347在Vivado下调试
简介 高速USB转接芯片CH347是一款集成480Mbps高速USB接口、JTAG接口、SPI接口、I2C接口、异步UART串口、GPIO接口等多种硬件接口的转换芯片。 通过XVC协议,将CH347应用于Vivado下,简单尝试可以成功,源码如下,希望可以一起共建&a…...
硬技能之上的软技巧(三)
在硬技能的基础上,如何运用软技巧来进一步提升个人能力和职业发展。在之前的讨论中,我们提到了硬技能和软技巧的基本概念,以及如何运用软技巧来提升个人能力和职业发展。本篇文章将进一步探讨软技巧中的一些重要方面,包括自我管理…...
mysql 查询
-- 多表查询select * from tb_dept,tb_emp; 内来链接 -- 内连接 -- A 查询员工的姓名 , 及所属的部门名称 (隐式内连接实现)select tb_emp.name,tb_dept.name from tb_emp,tb_dept where tb_emp.idtb_emp.id;-- 推荐使用select a.name,b.n…...
2311rust过程宏的示例
原文 Rust2018中的过程宏 在Rust2018版本中,我最喜欢的功能是过程宏.在Rust中,过程宏有着悠久而传奇的历史(并继续拥有传奇的未来!) 因为2018年版极大改善了定义和使用它们的体验. 什么是过程宏 过程宏是,在编译时用一段语法,生成新语法的函数.Rust2018中的过程宏有三个风格…...
数据分析:数据预处理流程及方法
数据预处理是数据分析过程中至关重要的一步,它涉及到清洗、转换和整理原始数据,以便更好地适应分析模型或算法。以下是一些常见的数据预处理方法和规则: 数据清洗: 处理缺失值:检测并处理数据中的缺失值,可…...
uniapp 防抖节流封装和使用
防抖(debounce):定义一个时间,延迟n秒执行,n秒内再次调用,会重新计时,计时结束后才会再次执行 主要运用场景: 输入框实时搜索:在用户输入内容的过程中,使用防抖可以减少频繁的查询…...
springcloud alibaba学习视频
阿里云登录 - 欢迎登录阿里云,安全稳定的云计算服务平台...
别再死记硬背AXI-Lite信号了!用握手协议的逻辑,5分钟理清5大通道
从握手协议视角重构AXI-Lite:用5个逻辑单元破解FPGA总线迷宫 第一次翻开AXI-Lite协议文档的工程师,往往会被密密麻麻的信号列表吓退——AWADDR、WDATA、BRESP、ARREADY...这些看似无序的字母组合,其实隐藏着精妙的系统级设计哲学。与其逐条背…...
基于MCP协议实现AI助手与Amazing Marvin任务管理系统的无缝集成
1. 项目概述:当AI助手遇见你的任务清单 如果你和我一样,既是Amazing Marvin的深度用户,又习惯了在Claude、Cursor这类AI助手的聊天窗口里解决大部分问题,那你肯定也经历过这种“割裂感”:想问问AI“我今天该先做什么”…...
Arm超分辨率技术解析与移动端优化实践
1. Arm Accuracy Super Resolution技术解析1.1 超分辨率技术基础原理超分辨率技术的本质是通过算法手段突破传感器硬件的物理限制,从低分辨率(LR)输入中重建出高分辨率(HR)图像。传统插值方法如双三次(bicubic)仅通过相邻像素加权计算新像素值,而现代基于…...
3分钟搞定:如何用Blender 3MF插件完美处理3D打印文件
3分钟搞定:如何用Blender 3MF插件完美处理3D打印文件 【免费下载链接】Blender3mfFormat Blender add-on to import/export 3MF files 项目地址: https://gitcode.com/gh_mirrors/bl/Blender3mfFormat 还在为Blender模型无法直接用于3D打印而烦恼吗ÿ…...
Neobrutalism组件库实战:用React构建高对比度UI界面
1. 项目概述:当“新粗野主义”撞上组件库如果你最近在逛一些设计社区或者前端开发者的社交平台,可能会频繁地看到一个词:Neobrutalism,翻译过来叫“新粗野主义”。这可不是什么建筑学的新流派,而是最近一两年在UI设计领…...
物联网设备暴露面激增,WAF如何守护边缘计算安全?
全球物联网设备数量已突破数百亿大关,从智能家居到工业传感器,从车联网到医疗设备,边缘计算正在重塑IT架构。然而,物联网设备的算力受限、固件更新困难、安全意识薄弱等特性,使其成为攻击者的理想跳板。2026年…...
开源情报实战指南:从工具到体系的OSINT方法论与自动化实践
1. 项目概述:一个开源情报收集的实战指南最近在整理自己的安全工具箱时,发现很多朋友对开源情报(OSINT)的实战应用很感兴趣,但往往止步于理论,或者被海量的工具和碎片化的信息淹没。恰好,我在Gi…...
Godot XR Tools:加速VR/AR开发的模块化工具集与实战指南
1. 项目概述:Godot XR Tools 是什么? 如果你正在用 Godot 引擎捣鼓 VR 或 AR 项目,大概率会遇到一些“通用但繁琐”的问题:怎么让虚拟手自然地抓取物体?怎么实现一个稳定可靠的传送移动机制?UI 界面在 3D …...
Vuforia Engine最新版在Unity中的完整配置避坑指南:从许可证Key到模型目标部署一步到位
Vuforia Engine最新版在Unity中的完整配置避坑指南:从许可证Key到模型目标部署一步到位 当你第一次在Unity中尝试用Vuforia Engine实现实体物体识别时,可能会被各种配置步骤和突发问题搞得手忙脚乱。本文将带你从零开始,避开所有常见陷阱&am…...
Git急诊室:5种报错急救指南,开发者入门教程
标题:GitHub急诊室:那些天天弹红字报错的“绝症”,其实都是纸老虎标签: Git报错、急救指南、VS Code、零基础避坑、保姆级教程前面咱们把分支、冲突、PR 这些“正规军”的打法全学完了。你以为从此以后就能在 GitHub 上纵横驰骋了…...
