【数据结构】6道经典链表面试题
目录
1.返回倒数第K个节点【链接】
代码实现
2.链表的回文结构【链接】
代码实现
3.相交链表【链接】
代码实现
4.判断链表中是否有环【链接】
代码实现
常见问题解析
5.寻找环的入口点【链接】
代码实现1
代码实现2
6.随机链表的复制【链接】
代码实现
1.返回倒数第K个节点【链接】
题目描述:
实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。

思路:快指针先走k步,然后快指针和慢指针同时走,直到快指针走到NULL,此时慢指针的节点即为所求。
解析:
代码实现
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/int kthToLast(struct ListNode* head, int k){struct ListNode*fast=head,*slow=head; //快指针先走k步while(k--){fast=fast->next;}//快慢指针一起走while(fast){slow=slow->next;fast=fast->next;}return slow->val;
}
2.链表的回文结构【链接】
题目描述:
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。
给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。

思路:首先找到中间节点,将中间节点后半部分倒置,再分别从头结点和尾节点向中间遍历,看对应值是否相等。
这里需要用到曾经写过的找链表的中间节点函数和反转链表函数可参照【单链表的应用】
代码实现
/*
struct ListNode {int val;struct ListNode *next;ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {public:/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/struct ListNode* middleNode(struct ListNode* head) {//创建快慢指针struct ListNode* slow = head;struct ListNode* fast = head;//如果有两个中间节点,则返回第二个中间节点while (fast && fast->next) {slow = slow->next;fast = fast->next->next;}//此时slow刚好指向中间节点return slow;}struct ListNode* reverseList(struct ListNode* head) {// 重新创建一个链表,将之前的链表进行头插即可struct ListNode* rphead = nullptr;// 进行指针变换struct ListNode* cur = head;while (cur != nullptr) {// 用于保存下一个节点地址struct ListNode* newnode = cur->next;// 头插cur->next = rphead;rphead = cur;cur = newnode;}return rphead; //返回新链表的头rhead}bool chkPalindrome(ListNode* A) {struct ListNode* mid = middleNode(A);struct ListNode* rmid = reverseList(mid);while (rmid && A) {if (rmid->val != A->val) {return false;}rmid = rmid->next;A = A->next;}return true;}
};
3.相交链表【链接】
题目描述:
给你两个单链表的头节点
headA和headB,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回null。

示例1相交节点不是1,而是8,注意这里不能比值,因为两个不同节点的值可能一样,要比较节点的地址。
思路1:暴力求解,对于链表A中的每个节点,我们都遍历一次链表B看B中是否有相同节点,第一个找到的就是第一个公共节点,假设A链表有M个节点,B链表有N个节点,时间复杂度太高了为O(M*N)即O(N^2)。
思路2:先判断两个链表是否相交,可以通过判断两个链表最后一个节点地址是否相同,如果尾节点相同,说明两个链表一定相交,如果不相等,直接返回空指针。计算出两个链表的长度,让长链表先走相差的长度,然后让两个链表同时走,直到遇到相同的节点就是第一个公共节点,返回指向这个节点的指针。
解析:

代码实现
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {struct ListNode *curA=headA,*curB=headB;int lenA=0,lenB=0;while(curA->next){curA=curA->next; ++lenA; }while(curB->next){curB=curB->next; ++lenB; //此时B链表的长度少算一个}//尾节点不相等就是不相交if(curA!=curB){return NULL;}lenA+=1;lenB+=1;//长的先走差距步,再同时走,第一个相等的就是交点//假设法int gap=abs(lenA-lenB);//求绝对值struct ListNode *longList=headA,*shortList=headB;//longList指向长链表,shprtList指向短链表//如果B比A长,再修改一下指针的指向,让longList指向长链表B,shprtList指向短链表Aif(lenB>lenA){longList=headB;shortList=headA;}while(gap--)//走差距步{longList=longList->next;}while(longList!=shortList){longList=longList->next;shortList=shortList->next;}return shortList;//返回哪一个都可以
}
4.判断链表中是否有环【链接】
题目描述:
给你一个链表的头节点
head,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪
next指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数pos来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos不作为参数进行传递 。仅仅是为了标识链表的实际情况。如果链表中存在环 ,则返回
true。 否则,返回false。

思路:首先,让快慢指针fast、slow指向链表的头节点head, 让快指针fast一次向后移动两个节点,慢指针一次向后移动一个节点, 判断fast和slow是否走到同一个节点上(数学上追击相遇问题),如果走到同一个节点上,就返回true。
代码实现
bool hasCycle(struct ListNode *head) {struct ListNode*slow=head,*fast=head;while(fast&&fast->next)//当一个链表中没有环时,fast一定会移动到链表的结尾{slow=slow->next;fast=fast->next->next;if(slow==fast){return true;}}return false;
}
常见问题解析
1.快慢指针为什么会相遇,它们有没有可能错过,永远追不上?
不会错过。
假设slow进环时,fast 和 slow 的距离是N,追击过程中二者距离变化如下:
N->N-1->N-2->……->3->2->1->0
每追击一次,二者之间距离缩小1,距离为0即相遇。
2.慢指针slow一次移动一个节点,快指针一次移动多个节点(3,4,5……n)可行吗?
可行。
用快指针一次移动3个节点举例
假设slow进环时,fast 和 slow 的距离是N,追击过程中二者距离变化如下:
情况1:N->N-2->N-4->……->4->2->0(N为偶数)
情况2:N->N-2->N-4->……->5->3->1->-1(N为奇数)N为-1表示错过了,距离变成C-1(C为环的长度)
- 如果C-1是偶数,新一轮追击就追上了
- 如果C-1是奇数,那么就永远追不上
如果N是奇数并且C是偶数,那么就永远追不上,那这种条件存在吗?
假设slow进环前走的距离为L,设slow进环时,fast已经在环中转了x圈
slow走的距离:L
fast走的距离:L+x*C+C-N
由fast走的距离是slow的三倍产生的数学等式:3L=L+x*C+C-N
化简得:2L=(x+1)*C-N
我们发现偶数=(x+1)*偶数-奇数不成立,反证出当N是奇数时,C也一定是奇数。
总结一下:一定能追上,N是偶数,第一轮就追上了;N是奇数,第一轮追不上,C-1是偶数,第二轮就追上了。
5.寻找环的入口点【链接】
题目描述:
给定一个链表的头节点
head,返回链表开始入环的第一个节点。 如果链表无环,则返回null。如果链表中有某个节点,可以通过连续跟踪
next指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数pos来表示链表尾连接到链表中的位置(索引从 0 开始)。如果pos是-1,则在该链表中没有环。注意:pos不作为参数进行传递,仅仅是为了标识链表的实际情况。不允许修改 链表。

思路1:用两个指针head、meet分别指向链表的头节点和快慢指针相遇的节点,同时移动两个指针,当两个指针指向同一个节点时,该节点就是环的入口点 。
解析:
假设环的长度为C,到达相遇点时,慢指针slow走过的距离为L+N(一圈之内肯定会被追上),快指针fast走过的距离为L+x*C+N (假设快指针走了x圈,N一定大于等于1),由fast走的距离是slow的2倍产生的数学等式:2*(L+N)=L+x*C+N 化简得:L=x*C-N
也就是说head到入口点的距离等于meet指针转x圈减去N的距离,head走到入口点,meet也刚好走到入口点,所以两个指针一起遍历,最终会同时到达入口点。
代码实现1
struct ListNode *detectCycle(struct ListNode *head) {struct ListNode *slow=head,*fast=head;while(fast&&fast->next){slow=slow->next;fast=fast->next->next;if(slow==fast){struct ListNode *meet=slow;while(meet!=head){meet=meet->next;head=head->next;} return meet;}}return NULL;
}
思路2:让快慢指针相遇节点与下一个节点断开,然后将问题转化为两个链表的相交,环的入口点其实就是两个链表的相交点。
解析:
代码实现2
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {struct ListNode *curA=headA,*curB=headB;int lenA=0,lenB=0;while(curA->next){curA=curA->next; ++lenA; }while(curB->next){curB=curB->next; ++lenB; //此时B链表的长度少算一个}//尾节点不相等就是不相交if(curA!=curB){return NULL;}lenA+=1;lenB+=1;//长的先走差距步,再同时走,第一个相等的就是交点//假设法int gap=abs(lenA-lenB);//求绝对值struct ListNode *longList=headA,*shortList=headB;//longList指向长链表,shprtList指向短链表//如果B比A长,再修改一下指针的指向,让longList指向长链表B,shprtList指向短链表Aif(lenB>lenA){longList=headB;shortList=headA;}while(gap--)//走差距步{longList=longList->next;}while(longList!=shortList){longList=longList->next;shortList=shortList->next;}return shortList;//返回哪一个都可以
}struct ListNode *detectCycle(struct ListNode *head) {struct ListNode *slow=head,*fast=head;while(fast&&fast->next){slow=slow->next;fast=fast->next->next;if(slow==fast){struct ListNode *meet=slow;struct ListNode *newhead=meet->next;meet->next=NULL; return getIntersectionNode(head,newhead);}}return NULL;
}
6.随机链表的复制【链接】
题目描述:
给你一个长度为
n的链表,每个节点包含一个额外增加的随机指针random,该指针可以指向链表中的任何节点或空节点。构造这个链表的 深拷贝。 深拷贝应该正好由
n个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的next指针和random指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。

深拷贝就是拷贝一个值和指针指向都跟当前链表一模一样的链表。
思路: 拷贝节点到原节点的后面,再寻找途径处理random指针,处理完后对复制的节点拿下来尾插成新链表,返回新链表的头。
解析:

代码实现
/*** Definition for a Node.* struct Node {* int val;* struct Node *next;* struct Node *random;* };*///拷贝节点插入在原节点的后面
struct Node* copyRandomList(struct Node* head) {struct Node*cur=head;while(cur){struct Node*copy=(struct Node*)malloc(sizeof(struct Node));copy->val=cur->val;copy->next=cur->next;//注意这里顺序不能颠倒cur->next=copy;cur=copy->next;}//控制randomcur=head;while(cur){struct Node*copy=cur->next;if(cur->random==NULL){copy->random=NULL;}else { copy->random=cur->random->next;}cur=copy->next; }//把拷贝节点取下来尾插成为新链表,然后恢复原链表struct ListNode*copyhead=NULL,*copytail=NULL;cur=head;while(cur){struct ListNode*copy=cur->next;struct ListNode*next=copy->next;if(copytail==NULL){copyhead=copytail=copy;}else{copytail->next=copy;copytail=copytail->next;}cur->next=next;//恢复原链表,有没有这句代码都行!cur=next;}return copyhead;
}
相关文章:
【数据结构】6道经典链表面试题
目录 1.返回倒数第K个节点【链接】 代码实现 2.链表的回文结构【链接】 代码实现 3.相交链表【链接】 代码实现 4.判断链表中是否有环【链接】 代码实现 常见问题解析 5.寻找环的入口点【链接】 代码实现1 代码实现2 6.随机链表的复制【链接】 代码实现 1.…...
等保测评1.0到2.0的演变发展
中国等保测评的演变 作为中国强化网络安全监管制度的重要组成部分,信息安全等级保护测评不是一个新概念,可以追溯到1994年和2007年发布的多项管理规则(通常称为等保测评 1.0规则),根据这些规则,网络运营商…...
yum 源配置
在/etc/yum.repo.d目录下 格式: [repository_name] nameRepository description baseurlhttp://repository_url enabled1 gpgcheck0 gpgkeyfile:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 其中: [repository_name]:源的标识名称,…...
通过AI技术克服自动化测试难点(上)
本文我们一起分析一下AI技术如何解决现有的自动化测试工具的不足和我们衍生出来的新的测试需求。 首先我们一起看一下计算机视觉的发展历史,在上世纪70年代,处于技术萌芽期,由字符的识别技术慢慢进行演化,发展到现在,人…...
等保测评:如何建立有效的网络安全监测系统
等保测评中的网络安全监测系统建立 在建立等保测评中的网络安全监测系统时,应遵循以下步骤和策略: 确定安全等级和分类:首先,需要根据信息系统的安全性要求、资产的重要性和风险程度等因素,确定网络系统的安全等级&…...
yjs12——pandas缺失值的处理
1.缺失值的表示 正常来说,pandas缺失值是“nan”表示,但是有且文件可能自己改成了相应的别的符号 2.如何将缺失值符号改成nan xxx.replace(to_replace"...",valuenp.nan) 3.判断是否有缺失值 1.pd.notnull(xxx)————如果有缺失,…...
噪声分布 双峰,模拟函数 或者模拟方法 python人工智能 深度神经网络
在Python中模拟双峰分布,可以通过多种方法实现。以下是一些常用的方法: 1. **使用正态分布混合**: 可以通过组合两个正态分布来创建一个双峰分布。每个正态分布都有其自己的均值(mu)和标准差(sigma&…...
5个免费ppt模板网站推荐!轻松搞定职场ppt制作!
每次过完小长假,可以明显地感觉到,2024这一年很快又要结束了,不知此刻的你有何感想呢?是满载而归,还是准备着手制作年终总结ppt或年度汇报ppt呢? 每当说到制作ppt,很多人的第一反应,…...
HTML5+Css3(背景属性background)
css背景属性 background 1. background-color背景颜色 背景颜色可以用“十六进制”、“rgb()”、“rgba()”或“英文单词”表示 2. background-image:url(路径);背景图片 也可以写成 background:url(); 3. background-repeat背景重复 属性值: - repeat:x,y平铺…...
高亚科技助力优巨新材,打造高效数字化研发项目管理平台
近日,中国企业管理软件资深服务商高亚科技与广东优巨先进新材料股份有限公司(以下简称“优巨新材”)正式签署合作协议,共同推进产品研发管理数字化升级。此次合作的主要目标是通过8Manage PM项目管理系统,提升优巨新材…...
用布尔表达式巧解数字电路图
1.前置知识 明确AND,OR,XOR,NOR,NOT运算的规则 参见:E25.【C语言】练习:修改二进制序列的指定位 这里再补充一个布尔运算符:NOR,即先进行OR运算,再进行NOT运算 如下图为其数字电路的符号 注意到在OR符号的基础上,在尾部加了一个(其实由简化而来) 附:NOR的真值表 2.R-S触发…...
面试--开源框架面试题集合
Spring 谈谈自己对于 Spring IoC 的了解什么是 IoC?IoC 解决了什么问题?什么是 Spring Bean?将一个类声明为 Bean 的注解有哪些?Component 和 Bean 的区别是什么?注入 Bean 的注解有哪些?Autowired 和 Resource 的区别是什么?…...
如何选择医疗器械管理系统?盘谷医疗符合最新版GSP要求
去年12月7日,新版《医疗器械经营质量管理规范》正式发布,并于今年7月1日正式实施。新版GSP第五十一条提出“经营第三类医疗器械的企业,应当具有符合医疗器械经营质量管理要求的计算机信息系统,保证经营的产品可追溯”,…...
shell 脚本批量更新本地git仓库
文章目录 一、问题概述二、解决方法三、运行效果1. windows2. centos 一、问题概述 你是否遇到这样的场景: 本地git仓库克隆了线上的多个项目,需要更新时,无法象svn一样,选中多个项目一起更新。 只能苦逼的一个个选中,…...
Linux相关概念和易错知识点(12)(命令行参数、环境变量、本地变量)
1.命令行参数 (1)main函数的参数int argc和char* argv[]是什么? main函数可以带参数,即int main(int argc, char* argv[]),(int argc, char* argv[])叫做命令行参数列表,int argc叫参数的个数&a…...
wenserver中 一些常见的 错误码
EINTR 是 Linux 系统中定义的一个错误码,代表“被信号中断”。当一个系统调用在执行过程中被一个信号处理函数中断时,这个系统调用会立即返回错误,并且 errno 被设置为 EINTR。 举个例子 read函数是阻塞的 现在没有数据要读 我们read一直阻…...
【电路笔记】-求和运算放大器
求和运算放大器 文章目录 求和运算放大器1、概述2、反相求和放大器3、同相求和放大器4、减法放大器5、应用5.1 音频混合器5.2 数模转换器 (DAC)6、总结1、概述 在我们之前有关运算放大器的大部分文章中,仅将一个输入应用于反相或非反相运算放大器的输入。在本文中,将讨论一种…...
java实现桌面程序开机自启动
问题: 最近用java写一个桌面闹钟程序,需要实现开机自启动功能 解决办法: jna官网:https://github.com/java-native-access/jna?tabreadme-ov-file 使用jna库可以轻松实现 下载jna-5.15.0.jar和jna-platform-5.15.0.jar这两个库…...
Vuex 使用实例
文章目录 Vuex介绍使用步骤安装使用定义配置文件代码解释: 导入到 App.vue使用使用vuex Vuex 介绍 简单来说就是,多个组件需要共享一个data,原本只能通过父子组件来进行,但是vuex可以实现共享data 使用步骤 安装 npm install v…...
深度分离卷积
深度可分离卷积(Depthwise Separable Convolution)是一种高效的卷积操作,它将传统卷积操作分解为两个独立的步骤:深度卷积(Depthwise Convolution) 和 逐点卷积(Pointwise Convolutionÿ…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...




