链表是否有环、环长度、环起点

问题引入

        如何检测一个链表是否有环,如果有,那么如何确定环的长度及起点。

引自博客:上述问题是一个经典问题,经常会在面试中被问到。我之前在杭州一家网络公司的电话面试中就很不巧的问到,当时是第一次遇到那个问题(毕竟太菜,没有专门准备过算法面试),我思考片刻,问答的是用一个哈希表存储访问的节点的地址,当访问某节点时,发现哈希表中已存在,表明链表中存在环。面试官听了我的回答就反问了我一句:如果链表的环很大,那么哈希表的空间消耗就很大,你的方法并不实用。你能在不消耗额外空间的情况下,找到链表的环吗?当时,想了很久没想到,面试官就说可以这样做,balabala...

算法描述

        解决上述问题的方法就是我们常说的快慢指针。乌龟与兔子在一个含环的跑道上(如图所求)进行比赛,乌龟在单位时间内移动一步,而兔子则在单位时间内移动两步,其移动速度是乌龟的两倍。乌龟与兔子同时从A点出发,兔子移动的快先行进入环形跑道,但那以后,一直在转圈。所以如果存在环的话,乌龟总能与兔子相遇(首次相遇在C点)。

        假设乌龟刚进入环时,兔子在环中任何一位置,此时二者相差距离为m,以后每运动一次兔子两步乌龟一步二者距离减少1,运动几次后距离总能变成0,所以慢指针走一步快指针走两步二者一定能相遇,但慢指针走一步快指针走三步或者其他组合方式可能并不一定能相遇需要注意。

  • 判断是否有环

        定义两个指针p1与p2,起始时,都指向链表的起点A,p1每次移动1个长度,p2每次移动2个长度。如果p2在移到链表的尾端时,并未与p1相遇,表明链表中不存在环。如果p1与p2相遇在环上的某一点C,表明链表有环。

  • 环的长度

        将指针p1固定在相遇位置C,移动p2,每次移动1个长度,并用变量cnt计数。当p2再次与p1相遇时,此时cnt的值就是环的长度。

  • 环的起点

        环的起点即图中点B,将指针p1指向链表的起始位置A,指针p2仍在位置C,指针p1与p2每次均移动一个单位,p1与p2再次相遇的位置就是环的起点位置点B。

简单证明

        上面求链表是否存在环及求环的长度的思路都很好理解,主要是为什么p1与p2再次相遇就是环的起点呢?这里假设从跑道的起始点A到环的起点B的路程为m,从B到相遇点C的路程为k,环的长度为n,相遇时乌龟的爬行路程为S1=m+k+t1*n,兔子的奔跑距离为S2=m+k+t2*n(t2>t1),兔子的速度是乌龟的两倍即S2=2*S1,则S1=S2-S1=(t2-t1)*n,S2=2*(t2-t1)*n,即兔子和乌龟相遇时的奔跑距离都为环的整数倍,而m+k=(t2-2*t1)*n也为环的整数倍。当兔子回到跑道的起始位置,乌龟从相遇点B出发时,这时,两人的速度均为单位时间内爬行1个长度,当兔子到达环的起点B即爬行了m距离时,乌龟则是k+m,此时刚好爬行环的整数倍,也处于环的起点B,即乌龟与兔子再次相遇的位置即为环的起点位置B。

参考链接:弗洛伊德的兔子与乌龟

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

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

相关文章

RocketMQ集群4.9.2升级4.9.6版本

本文主要记录生产环境短暂停机升级RocketMQ版本的过程 一、整体思路 1.将生产环境MQ4.9.2集群同步到测试环境,并启动,确保正常运行。 2.参照4.9.2配置4.9.6集群 3.停掉4.9.2集群,启动4.9.6集群,测试确保正常运行。 4.停掉4.9.6集…

JSON格式Python,Java,PHP等封装获取淘宝商品快递费用数据API方法

淘宝是一个网上购物平台,售卖各类商品,包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取淘宝天猫商品详情快递费用数据,您可以通过开放平台的接口或者直接访问淘宝天猫商城的网页来获取商品详情快递费用。以下是两种常用方法的介绍&a…

leetcode132. 分割回文串 II(java)

分割回文串 II 分割回文串 II动态规划 回文字符串 分割回文串 II 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文。 返回符合要求的 最少分割次数 。 示例 1: 输入:s “aab” 输出:1 解释:…

git使用教程

一 创建环境 参考 Git 安装配置 | 菜鸟教程 (runoob.com)https://www.runoob.com/git/git-install-setup.html 1.1 配置 $ git config --global user.name "runoob" $ git config --global user.email test@runoob.com 1.2 创建一个新文件夹 在新的文件夹执行(…

C++中的头文件.h 和 源文件.cpp 的关系

在VS中 C项目,我创建了一个类, 会自动创建头文件和源文件,这两个文件有什么关系? 如何快速切换?在头文件.h文件中声明的类方法, 如何快速在源文件中进行具体实现?在 Visual Studio 中创建 C 项…

多级调度在工程中的应用及思路

多级调度在工程中的应用及思路 集中式多机调度 顾名思义:集中式多机调度就是指,机器的数据是集中的,有统一的控制中心调度,类似于现实中的机场调度中心,铁路调度中心,一般机器将定位,速度&…

文件上传漏洞总结2

文件上传的大体都已经学习过了 这个假期在给他强化一下 什么是webshell webshell是web入侵的脚本攻击工具。webshell就是一个asp或php木马后门,黑客在入侵了一个网站后,常常在将这些asp或php木马后门文件放置在网站服务器的web目录中,与正常…

HTML5的应用现状与发展前景

HTML5,作为Web技术的核心,已经深深地改变了我们看待和使用Web的方式。它不仅提供了数不尽的新特性和功能,还使得Web设计和开发更加互动、更加直观。这篇文章将探讨HTML5的当前应用现状,以及它的未来发展前景。 HTML5的应用现状 H…

HDU-7323 2023“钉耙编程”杭电多校赛(3)a-b Problem

HDU-7323 2023“钉耙编程”杭电多校赛(3)a-b Problem 题目大意 小 A A A和小 B B B在玩游戏。有 n n n块石头,小 A A A和小 B B B轮流捡,小 A A A先捡。每人每次只能捡一块石头,直到所有的石头都被捡完。 每块石头都…

【linux升级ssh】 利用rpmbuild工具对ssh打包为rpm包进场安装升级

制作rpm包 rpmbuild命令用于创建软件的二进制包和源代码包。 官方文档:rpm.org - RPM Reference Manual rpmbuild 中文手册:rpmbuild 中文手册 [金步国] 使用rpmbuild将tar包打成rpm包 RPM打包使用的是rpmbuild命令,这个命令来自rpm-buil…

二、深入浅出WPF之系统学习XAML语法

二、系统学习XAML语法 2.1 Xaml的树形结构 跟Winforms一样,UI也是个平面结构,与winforms的设计思维不同,WPF使用树形逻辑来描述UI,下面是UI布局的简单代码 <StackPanel Background="LightBlue"><TextBox x:Name="textBox1" Margin="5&q…

本地缓存LoadingCache

引入依赖 <!-- https://mvnrepository.com/artifact/com.google.guava/guava --> <dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>32.1.1-jre</version> </dependency>主要代…

(三)InfluxDB入门(借助Web UI)

以下内容来自 尚硅谷&#xff0c;写这一系列的文章&#xff0c;主要是为了方便后续自己的查看&#xff0c;不用带着个PDF找来找去的&#xff0c;太麻烦&#xff01; 第 3 章 InfluxDB入门&#xff08;借助Web UI&#xff09; 借助Web UI&#xff0c;我们可以更好地理解InfluxD…

C语言入门篇(八)

前言   本篇分享的是部分操作符的概念与用法&#xff0c;从经典例题入手&#xff0c;带你快速了解和掌握。   收录专栏&#xff1a;浅谈C语言 操作符详解上 1. 操作符分类2. 算术操作符3. 移位操作符3.1 左移操作符3.2 右移操作符 4. 位操作符5. 赋值操作符6. 单目操作符6.…

Excel双向柱状图的绘制

Excel双向柱状图在绘制增减比较的时候经常用到&#xff0c;叫法繁多&#xff0c;双向柱状图、上下柱状图、增减柱状图都有。 这里主要介绍一下Excel的基础绘制方法和复杂一点的双向柱状图的绘制 基础双向柱状图的绘制 首先升降的数据如下&#xff1a; 月份上升下降20220359-…

如何创建高级 CSS 下拉菜单

效果展示 实现思路及部分代码 1、定义整体页面结构 从上述的效果展示图可以看出&#xff0c;页面的整体结构应该需要一个总菜单容器来装载父级菜单项&#xff0c;并且对应的父级菜单项应该有对应的菜单子项。子菜单是分类的话&#xff0c;我们还需要额外在扩展对应的容器来装…

代码随想录算法训练营day11 | 20. 有效的括号,1047. 删除字符串中的所有相邻重复项

目录 20. 有效的括号 1047. 删除字符串中的所有相邻重复项 150. 逆波兰表达式求值 20. 有效的括号 难度&#xff1a;easy 类型&#xff1a;栈与队列 思路&#xff1a; 利用栈来做括号匹配&#xff1b; 代码&#xff1a; class Solution {public boolean isValid(String…

Django全局捕获view函数中的所有异常、Python中获取异常(Exception)信息

文章目录 一、Django全局捕获view函数中的所有异常1. 使用中间件2. 使用视图装饰器3. DRF(Django REST framework)全局异常处理【重要】在 Django 中,self.get_response(request) 返回的是一个处理过的响应对象4. Django全局捕获view函数中的所有异常 演示demo二、Python中获取…

Unity UGUI的RectMask2D(2D遮罩)组件的介绍及使用

Unity UGUI的RectMask2D&#xff08;2D遮罩&#xff09;组件的介绍及使用 1. 什么是RectMask2D组件&#xff1f; RectMask2D是Unity UGUI中的一个组件&#xff0c;用于实现2D遮罩效果。它可以限制子对象在指定的矩形区域内显示&#xff0c;超出区域的部分将被遮罩隐藏。 2. …

Flutter 最佳实践和编码准则

Flutter 最佳实践和编码准则 视频 前言 最佳实践是一套既定的准则&#xff0c;可以提高代码质量、可读性和可靠性。它们确保遵循行业标准&#xff0c;鼓励一致性&#xff0c;并促进开发人员之间的合作。通过遵循最佳实践&#xff0c;代码变得更容易理解、修改和调试&#xff…