经典面试题---环形链表

1. 环形链表1. - 力扣(LeetCode)

 

要解决这道题,我们首先要挖掘出带环的链表与不带环的链表之间的差别。

以此,才能设计出算法来体现这种差别并判断。

二者最突出的不同,就是不带环的链表有尾结点,也就是说在访问到某个结点时,其next指针可能为NULL。

而带环的链表则没有尾结点,负责访问链表的指针进入环以后,就会一直在环中转圈。

 但是,仅靠这个,我们很难解决这个问题。

按以上得到的信息来说,我们会尝试去1. 检查该链表是否有尾结点,或者2. 检查有无结点被重复访问

对于第一种思路,很明显行不通,因为在检查一个带环的链表时,我们会一直访问不到尾结点,但我们也无法找到确切的指标来证明该链表确实没有尾结点。

对于第二种思路,一般来说,我们会想到将已访问过的结点的地址保存起来,每访问一个结点,我们就检查已保存的地址中是否有与新结点地址相同的地址。

第二种思路没有任何问题,确实可以顺利解决这个问题,那么我们来看看进阶要求。

很明显,第二种思路写出的算法的时间复杂度为O(n!),空间复杂度为O(n)。

也就是说还有更妙的办法,或者说带环链表和不带环链表之间还有更加值得利用的区别。

仔细观察就能发现,带环会改变环中结点之间的相对关系。

当链表不带环时,我们可以肯定地说:值为2的结点在值为-4的结点之前。

但是,当链表带环时,我们却可以认为值为-4的结点在值为2的结点之前,因为值为-4的结点的next指针指向的是值为2的结点。

也就是说,带环改变了环中结点之间的前后相对关系。

那么,我们如何使得这种差异体现出来呢?

这使得我们想到快慢指针

假设快慢指针的都从头结点开始移动。

当链表不带环时,快慢指针一旦分开便再无相遇的可能;

当链表带环时,由于环中结点的相对关系被改变,在快慢指针都进入环之后,原本在前的快指针可以认为是在慢指针之后,那么快指针就会不断追击慢指针,最终二者可能相遇。

但是,我们如何确保快指针最后一定会追上慢指针呢?

在追击过程中,二者每次移动,它们之间的距离的减少量就是二者的速度之差。

由于在慢指针刚进入环时,二者之间的距离一定为整数,所以当二者的速度之差为1时,它们就必定相遇。

依据此思路,我们可以设计出如下的算法:

typedef struct ListNode ListNode;bool hasCycle(struct ListNode *head) {ListNode* slow = head;ListNode* fast = head;while(fast && (fast->next)){fast = fast->next->next;slow = slow->next;if(fast == slow)return true;}return false;
}

很明显,该算法的时间复杂度为O(n),空间复杂度只有O(1),满足的进阶的要求并明显减小了时间复杂度。

2. 数学分析

完成这道题还不足以让你通过面试,接下来面试官可能会问你:

1. 二者为什么一定会相遇呢?

2. 慢指针每次前进一个结点,快指针每次前进三个结点可以吗?四或五个结点呢?

 第一个问题我们在解题的过程中就已经解决,你只要将思路清晰地阐述即可。

对于第二个问题,要让面试官刮目相看,我们自然不满足于只解决给出的三种情况(对具体情况单独分析也挺麻烦的),我们会尝试给出判断可行的数学公式。

我们假设:

1. 环的周长为c(环有c个结点)。

2. 当慢指针刚进入环时,快指针已经在环中移动的长度为L。

3. 快指针的速度为k(每次移动k个结点)。

4. 慢指针进入环之后,移动n次时与快指针相遇。

 将进入环的第一个结点标记为下标0,随后结点的下标依次递增,直到再次遇到下标为零的结点。

 二者相遇时,快慢指针的位置是相同的。

据此,当二者相遇时,一定满足这个表达式:(nk + L) % c = n % c

假设相遇时,快指针比慢指针多走了m圈,则有:nk + L = n + mc

移项可得:n = (mc - L) / (k - 1)

由于n为整数,所以,如果存在m使得(mc - L) % (k - 1) = 0,我们就可以认为二者一定会相遇。

很明显,当k = 2时,上式一定成立(任何整数都可以整除1),这也就验证了我们之前的结论。

而当k > 2时,上式能否成立则受到c与L的影响,无法保证一定成立。

3. 环形链表2. - 力扣(LeetCode)

 也就是在刚才的基础之上,要求我们求出环中的第一个结点。

这个时候,我们之前想到的第一种思路似乎就能派上用场了:如果找到了重复访问的结点,直接返回该结点的地址即可。

但是,这道题依然有同样的进阶要求:

同样的要求,也就是在提示我们这道题的最佳思路一定是建立在第一题的解法之上。

那么在第一题判断该链表有环之后,我们要如何找到环中第一个结点呢?

不妨先考虑一下,当快慢指针相遇时,二者在哪个位置。

当慢指针刚好进入环时,快指针的坐标为L % c。

按照快指针追击慢指针的角度来看,快慢指针之间相距的距离为c - (L % c)。

每移动一次,二者之间的距离会缩短1,那么二者共会移动c - (L % c)次。

所以,最终慢指针的坐标会停留在c - (L % c)处,也即二者相遇时的坐标。

此时,慢指针要再次到达下标为0的结点(环中第一个结点),需要再移动(L % c)次。

注意到,L = (L % c) + xc(x为整数)。

也就是说,让慢指针移动L次,其也依然会到达下标为0处(多绕x圈)。

可是,此时,我们怎么知道L是多少呢?

仔细观察会发现,头结点到环中第一个结点的距离恰好就是L。

因为快指针的速度是慢指针的两倍,所以,在进环之前,头结点到慢指针的距离与慢指针到快指针的距离是相等的。

在慢指针恰好进入环时,头结点到环中第一个结点的距离就等于慢指针到快指针的距离,即L。

所以,我们只需要让头结点处的指针和相遇处的指针同时开始移动(每次一个结点),最终就会在下标为0的结点处相遇。

依据这个思路,我们可以写出如下代码:

typedef struct ListNode ListNode;struct ListNode *detectCycle(struct ListNode *head) {ListNode* slow = head;ListNode* fast = head;while(fast && (fast->next)){fast = fast->next->next;slow = slow->next;if(fast == slow){ListNode* meet = slow;while(meet != head){meet = meet->next;head = head->next;}return meet;}}return NULL;
}

4. 结语

如果你在面试中遇到了这道题并清晰流畅地答出了本文的内容,那么你的面试就稳了一半了。

如果觉得写的不错就三连支持一下吧!

加纳……

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

顺序表经典算法OJ题-- 力扣27,88

题1: 移除元素 题2: 合并两个有序数组 一:题目链接:. - 力扣(LetCode) 作答: 二:题目链接:. - 力扣(LeetCode) 作答: 感谢观看&am…

速看!这次主食冻干评测极可能被商家恶意举报~VE、希喂、PR真实测评

我发现还是有不少铲屎官局限于“进口最高贵”,盲目的迷信进口产品。看到进口粮就盲买,甚至过分的贬低国产品牌,将国产粮贴上“不靠谱”“不合格”等标签。 最近,我针对主食冻干的国内、国际标准,相关规范文件&#xf…

windows安装ElasticSearch以及踩坑

1.下载 elasticsearch地址:Past Releases of Elastic Stack Software | Elastichttps://www.elastic.co/cn/downloads/past-releases#elasticsearch IK分析器地址:infinilabs/analysis-ik: 🚌 The IK Analysis plugin integrates Lucene IK…

c++ 线程交叉场景试验

1.需求 1.处理一个列表的数据,要求按照列表的数据处理10个数据 2.可以使用多线程处理,但是针对每个线程,1~10的处理顺序不能变。 3.每个数据的处理必须原子,即只有一个线程可以针对某个数据进行处理,但是10个数据是可…

保姆级教程:从 0 到 1 将项目发布到 Maven 中央仓库【2024年5月】

前言 大家好,我叫阿杆,不叫阿轩 最近写了一个参数校验组件,名字叫 spel-validator,是基于 javax.validation 的一个扩展,目的是简化参数校验。 我把项目开源到了GitHub https://github.com/stick-i/spel-validator …

视频号小店是普通人的机会吗?看完你就明白了!

大家好,我是电商小V 视频号小店是普通人的机会吗?我可以很确定的说:视频号小店就是普通人的机会,并且是很大的机会, 首先就是视频号小店这个项目还没有自然流量的入口,是一个还没有完全开放私域电商的平台&…

HNU-人工智能-实验4-基于Resnet的分类器

前言 本实验是自选实验,可以在给定范围内选择。 我刚刚提交了实验报告,暂时不准备放出我自己的实验报告,大概在截止提交之后我再放。 之所以这么着急写blog,是想便利还没做实验的同学。 如果选择的也是这个“毒蘑菇识别”的分类器…

一文读懂计算机视觉4大任务:分类任务、检测任务、目标分割任务、关键点检测任务

《博主简介》 小伙伴们好,我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~ 👍感谢小伙伴们点赞、关注! 《------往期经典推…

电脑桌面备忘录在哪里设置?好用的电脑桌面备忘录软件

在日常工作和生活中,电脑桌面备忘录的重要性不言而喻。想象一下,在繁忙的工作中,你能够一眼看到桌面上的备忘录提醒,从而及时完成重要任务,或者在紧张的学习中,通过备忘录快速回顾关键知识点。一款优秀的电…

翻译《The Old New Thing》 - Understanding the consequences of WAIT_ABANDONED

Understanding the consequences of WAIT_ABANDONED - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20050912-14/?p34253 Raymond Chen 2005年09月12日 理解 WAIT_ABANDONED 的后果 简要 文章讨论了在多线程同步中,如果一个线程…

轨道交通巡检机器人的应用范围

在现代轨道交通系统的庞大网络中,无数的轨道、设备和设施交织在一起,如同一个精密的机器在高效运转。而在这背后,轨道交通巡检机器人正悄然登场,它们如同一个个智能的守护者,穿梭于各个场景之中。那么,这些…

民航电子数据库:replace into导致自增主键异常,新增数据时报错:违反唯一键约束

目录 场景异常原因解决方法一:删除数据重新insert方法二:刚刚自增主键的起始值 场景 1、对接民航电子数据库 2、由于truncate、drop命令会使数据库报错:执行失败,[E14011]资源忙(加锁超时),所以用了replace into命令…

【PCB字符批量修改】- PCB板工艺及AD软件配置

软件版本 选择丝印-单机右键,选择find similar objects 第二步单机Apply 第三步选择OK 第四步在Panels中选择Properties里面修改Text Height和Stroke Width 到此搞定!

代码随想录刷题随记30-贪心4

代码随想录刷题随记30-贪心4 860.柠檬水找零 leetcode链接 比较显然 class Solution {public boolean lemonadeChange(int[] bills) {int []accountnew int[3];for(int cur:bills){if(cur5)account[0];else if(cur10){account[0]--;if(account[0]<0)return false;account…

53. 【Android教程】Socket 网络接口

Socket 网络接口 大家在学习计算机网络的时候一定学习过 TCP/IP 协议以及最经典的 OSI 七层结构&#xff0c;简单的回忆一下这 7 层结构&#xff1a; 从下到上依次是&#xff1a; 物理层数据链路层互联层网络层会话层表示层应用层 TCP/IP 协议对这 7 层了做一点精简&#xff…

【MySQL | 第八篇】在MySQL中,如何定位慢查询以及对应解决方法?

文章目录 8.在MySQL中&#xff0c;如何定位慢查询以及对应解决方法&#xff1f;8.1MySQL慢查询日志8.1.1开启慢查询&#xff08;1&#xff09;修改配置文件&#xff08;2&#xff09;设置全局变量 8.1.2日志记录在表上&#xff08;实践&#xff09;8.1.3日志记录在文件上&#…

redis分片java实践、redis哨兵机制实现、redis集群搭建

redis分片java实践 linux安装redishttps://mp.csdn.net/mp_blog/creation/editor/134864302复制redis.conf配置文件成redis1.conf、redis2.conf、redis3.conf 修改redis的端口信息和存pid文件的路径。存pid文件的路径只要不同就行了&#xff0c;没什么特别要求。 指定配置文件…

MySQL安装文档(8.0.37)

MySQL安装文档 前言1 下载2 解压3 环境3.1 添加环境变量3.2 初始化MySQL3.1 注册MySQL服务4 启动MySQL服务5 修改默认账户密码 4 登录MySQL5 卸载MySQL 前言 数据库&#xff1a;英文为 DataBase&#xff0c;简称DB&#xff0c;它是存储和管理数据的仓库。 数据库管理系统&…

ISIS的工作原理

1.邻居关系建立 &#xff08;1&#xff09;IS-IS领接关系建立原则 1、通过将以太网接口模拟成点到点接口&#xff0c;可以建立点到点链路邻接关系。 2、当链路两端IS-IS接口的地址不在同一网段时&#xff0c;如果配置接口对接收的Hello报文不作IP地址检查&#xff0c;也可以建…

若依plus 某些接口(用户信息等)响应突然变慢

今天一大早起来发现我的接口突然响应变慢了&#xff01; 就什么都没动&#xff0c;啥也没改&#xff0c;但是一些接口又很快。 百度了很多&#xff0c;都说叫我改sql查询方式&#xff0c;又怀疑是过滤器的问题&#xff0c;很遗憾都不是&#xff01; 一个响应40秒&#xff01;…