当前位置: 首页 > news >正文

【数据结构】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,很多人的第一反应&#xff0c…...

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一样,选中多个项目一起更新。 只能苦逼的一个个选中&#xff0c…...

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&#xff…...

JSONL 文件的检查和修订器

下面是一个JSONL 文件的检查和修订器,代码如下: import json import tkinter as tk from tkinter import filedialog, messageboxdef check_jsonl_file(input_file, log_file, output_file=None):errors = []valid_lines = []with open(input_file, r, encoding=utf-8) as in…...

输电线路悬垂线夹检测无人机航拍图像数据集,总共1600左右图片,悬垂线夹识别,标注为voc格式

输电线路悬垂线夹检测无人机航拍图像数据集,总共1600左右图片,悬垂线夹识别,标注为voc格式 输电线路悬垂线夹检测无人机航拍图像数据集介绍 数据集名称 输电线路悬垂线夹检测数据集 (Transmission Line Fittings Detection Dataset) 数据集…...

杭电合集小tips

刷HDU的题过程中&#xff0c;有一些值得注意的小问题&#xff0c;这里我踩坑之后记录下来&#xff0c;以便回顾与各位分享 一&#xff0c;关于语言的使用 主要大家还是用C和C多&#xff0c;但是注意的是&#xff0c;#include<bits/stdc.h>这个文件是G自带的&#xff0c…...

Python的输入输出函数

1.输入函数 Python的输入函数是input().input的引号里面是提示的内容&#xff0c;从键盘输入的任何字符都会当成字符串赋值给变量. n input("请输入:") print(type(n)) print(n) 输出结果为&#xff1a; 请输入:33 <class str> 33 2.输出函数 Python的内置…...

如何进行搭建与部署云主机?

云主机是一种基于虚拟化技术的服务器&#xff0c;云主机可以为用户提供一种非常高效且可扩展的计算机资源服务&#xff0c;主要是由操作系统和云硬盘等基础的计算组件所构成的&#xff0c;用户能够根据自身的需求来选择相关的配置规格&#xff0c;来满足不同的业务需求。 那么我…...

Biomamba求职| 国奖+4篇一作SCI

转眼间我也要参加秋招啦&#xff0c;认真的求职帖&#xff0c;各位老师/老板欢迎联系~其它需要求职的小伙伴也欢迎把简历发给我们&#xff0c;大家一起找工作。 一、基本信息 姓名&#xff1a;Biomamba 性别&#xff1a;男 出厂年份&#xff1a;1998 籍贯&#xff1a;浙江…...

Python 工具库每日推荐 【Pandas】

文章目录 引言Python数据处理库的重要性今日推荐:Pandas工具库主要功能:使用场景:安装与配置快速上手示例代码代码解释实际应用案例案例:销售数据分析案例分析高级特性数据合并和连接时间序列处理数据透视表扩展阅读与资源优缺点分析优点:缺点:总结【 已更新完 TypeScrip…...

电影选票选座系统|影院购票|电影院订票选座小程序|基于微信小程序的电影院购票系统设计与实现(源码+数据库+文档)

电影院订票选座小程序 目录 基于微信小程序的电影院购票系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户功能实现 2、管理员功能实现 &#xff08;1&#xff09;影院信息管理 &#xff08;2&#xff09;电影信息管理 &#xff08;3&#xff09;已完成…...

matlab初学习记录

文章目录 内置函数与变量matlab 编辑器数组等间距向量数组函数数组索引提取多个元素 对向量执行数组计算查看文档 画图添加注释 实践导入数据关系运算符分支恒星运动 matlab 学习看入门之旅 先计算等号右边再计算等号左边。 工作区记录等号右边的变量。 ; 表示的是抑制输出。…...

protobuf之Message

简介 Message是protobuf的消息抽象类&#xff0c;是其它通过protoc生成的自定义消息的基类 结构 #mermaid-svg-u5iAZNpfIH5hQrlP {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-u5iAZNpfIH5hQrlP .error-icon{fil…...