判断环形链表是否有环??返回环形链表的入口点!!

news2024/9/29 21:26:30

上次笔者写了一篇大概有7个题的链表相关的题目+解析,感觉还不错,感兴趣的各位老铁,可以点一下链接进行欣赏:做几个与链表相关的题吧!https://blog.csdn.net/weixin_64308540/article/details/128550685?spm=1001.2014.3001.5502那么,接下来就该进入:环形链表部分了!!

141. 环形链表

给你一个链表的头节点 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

解释:链表中没有环。

提示:

  • 链表中节点的数目范围是 [0, 104]

  • -105 <= Node.val <= 105

  • pos 为 -1 或者链表中的一个 有效索引

进阶:你能用 O(1)(即,常量)内存解决此问题吗?

上述是力扣中的题目!如果你已经看完了题目,那么,就该跟着笔者进入正文解析了!!

根据链表的基础知识,我们可以得出:如果一个链表是环形链表,那么最后一个节点一定存储了前面某个节点的地址!!

思路:快慢指针:

快慢指针,即慢指针一次走一步,快指针一次走两步,两个指针从链表的起始位置(头节点)开始进行,如果链表带环,则快指针与慢指针一定会在环中相遇!!否则,快指针一定会率先走到链表的尾部,比如,陪女朋友到操场跑步减肥!!

扩展问题:

  1. 为什么快指针一次走两步,慢指针一次走一步可以??

假设链表带环,两个指针最后都会进入环,快指针先进入环,慢指针后进入环,当慢指针刚进入环时候,可能就与快指针相遇了,最差的情况下,两个指针的距离就是环的长度!此时两个指针每移动一次,之间的距离就缩小一步,,不会出现每次刚好是套圈的情况,因此,在慢指针走一圈之前,快指针肯定可以追上慢指针的!即相遇!

2.快指针一次走3步,走4步,...n步行吗? 假设有环的情况下:快指针每次走3步,慢指针每次走1步,此时快指针肯定先进环,慢指针后来才进环,假设慢指针进环的时候,快慢指针的相对位置如图所示:

此时按照上述的假设:快指针每次走3步,慢指针每次走1步,来绕环移动,是永远不会相遇的!!此时进行了套圈!!

因此,只有快指针走2步,慢指针走1步才可以,换的是最小长度是1,即使套圈了,两个也能在相同位置!!

此时我们可以看出,环的问题,可以大致理解为:追及相遇的问题!!

那么,有了这些想法,我们还应该判断没环的情况下的问题:

经过上述的分析,我们可以看出当没环条件下的结束条件!

因此,我们有着下述的简单代码:写法1:

 public boolean hasCycle(ListNode head){
        ListNode fast=head;
        ListNode slow=head;
        while (fast != null && fast.next !=null){  //没环的情况下!
            fast=fast.next.next;
            slow=slow.next;
            if (fast==slow){
                return true;
            }
        }
        return false;
    }

写法2:

    public boolean hasCycle2(ListNode head){
        ListNode fast=head;
        ListNode slow=head;
        while (fast != null && fast.next !=null){
            fast=fast.next.next;
            slow=slow.next;
            if (fast==slow){
                break;//出while循环(有两种可能)
            }
        }
        if (fast==null ||fast.next==null){//排除不是环的可能
            return false;
        }
            return true;       
    }

经过这个题目,我们可以思考一下,如何进行手动置环??

手动置环问题:遍历一遍链表,找到尾巴节点,其所对应的next本为null,将其改为前面任意节点的地址就可以了(保证有)!!

   //手动置环
    public void creatLoop(ListNode head){
        ListNode cur=head;
        while (cur.next !=null){
            cur=cur.next;//找尾巴节点
        }
        cur.next=head.next.next;//保证有该节点!
    }

142. 环形链表 II

给定一个链表的头节点 head ,返回链表开始入环的第一个节点如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos-1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

示例 1:

输入:head = [3,2,0,-4], pos = 1

输出:返回索引为 1 的链表节点

解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0

输出:返回索引为 0 的链表节点

解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入:head = [1], pos = -1

输出:返回 null

解释:链表中没有环。

提示:

  • 链表中节点的数目范围在范围 [0, 104] 内

  • -105 <= Node.val <= 105

  • pos 的值为 -1 或者链表中的一个有效索引

进阶:你是否可以使用 O(1) 空间解决此题?

对于这个题目,显得有点儿难度!!

结论 让一个指针从链表起始位置开始遍历链表,同时让一个指针从判环时相遇点的位置开始绕环运行,两个指针都是每次均走一步,最终肯定会在入口点的位置相遇。 证明

这个是主要的思路,或许你看不懂,没关系,那么请看一下笔者的推论吧!!

我们有着以下的简单思路:

  1. 当在最好的情况下:我们有着:fast多走一圈,然后与slow在相遇处相遇,此时,fast走的路程为:X+C(C-Y)  此时,slow走的路程:X+(C-Y),由于fast的速度是slow的二倍,则路程也是2倍,即有着一下结论:2*(X+C-Y)=X+C+(C-Y)  经过计算,我们可以得到;X==Y

  1. 当不最好的情况下:fast走了很多圈,才与slow在相遇点相遇,此时说明,环的长度C很小很小!!

此时,fast走的路程为:X+NC(C-Y) 此时,slow走的路程:X+(C-Y),由于fast的速度是slow的二倍,则路程也是2倍,即有着一下结论:2*(X+C-Y)=X+NC+(C-Y) 经过计算,我们可以得到;X==(N-1)*C+Y 因此,当N很大很大的时候,说明环很小很小了,而fast多走的长是从相遇点开始的!

注意:

  1. 当慢指针进入环时候,快指针可能已经在环中绕了N圈了,N至少为1,因为当快指针先到环走到相遇点的位置,慢指针还没有进环!

  1. 慢指针进入环以后,快指针肯定会在慢指针走一圈之内追上慢指针,因为:快指针进环之后,快慢指针之间的距离最多就是环的长度,而两个指针在移动的时候,每次他们之间的距离都会缩减1步,因此,慢指针移动一圈之前,快指针一定可以追上慢指针的!!

下面请看笔者的代码吧!!代码起很简单,但是思路很重要!!

  //返回循环链表的相交节点
    public ListNode detectCycle(ListNode head){
        ListNode fast=head;
        ListNode slow=head;
        //先判断链表中是否有环??
        while (fast != null && fast.next !=null){
            fast=fast.next.next;
            slow=slow.next;
            if (fast==slow){
                break;
            }
        }
        if (fast == null || fast.next == null){
            return null;
        }
        //此时fast与slow已经在相遇点相遇了!
        slow=head;//将fast或者slow任意一个拉回头节点head
        while (fast !=slow){
            fast=fast.next;
            slow=slow.next;
        }//当fast与slow再次相遇的时候,即为入口点
        return fast;
    }

对于这个代码,想必各位老铁都能看懂吧!!

由于在码字的过程中,出现了些许差错,导致有点错别字!!勿怪!勿怪!

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

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

相关文章

CPT205-Computer Graphics(2)

文章目录7. Hierarchical Modelling7.1 Local and world co-ordinate frames of reference7.1.1 Relative motion7.2 Linear modelling7.3 Hierarchical modelling7.3.1 Hierarchical transformations8. Lighting and Materials8.1 Lighting sources8.1.1 Point light8.1.2 Dir…

如何将revit的内建模型导出使用?项目族管理功能介绍

Revit中内建模型建模是我们常用的功能&#xff0c;每次建模完成后都可以在另一个项目中使用&#xff0c;但是前提是需要导出后再载入才能在另一个项目中使用。今天就教教大家如何将Revit的内建模型单独导出&#xff0c;方便大家下次使用在其它项目。 如何将revit的内建模型单独…

计算机组成原理_总线的性能指标

计算机组成原理总目录总线的性能指标 一、总线周期和时钟周期 总线周期 总线周期通常指的是CPU完成一次访问内存或I/O端口操作所需要的时间 其中包括申请阶段、寻址阶段、传输阶段和结束阶段时钟周期 时钟周期是处理操作最基本的单位&#xff0c;在一个时钟周期内&#xff0c;…

【历史上的今天】1 月 9 日:iPhone 问世;iTunes 发布;激光打印机的发明者出生

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2023 年 1 月 9 日&#xff0c;在 1978 年的这段时间&#xff0c;我国恢复了研究生制度&#xff0c;这一年&#xff0c;共录取了 10500 多名研究生。研究生教育的中断和…

哈希的应用 —— 布隆过滤器

目录 一、布隆过滤器的提出 二、布隆过滤器的介绍 1. 基本概念 2. 布隆过滤器的特点 3. 哈希函数和布隆过滤器的长度对误判的影响 三、布隆过滤器的实现 1. 布隆过滤器的插入 &#xff08;Set接口&#xff09; 2. 布隆过滤器的查找&#xff08;Test接口&#xff09; …

javascript原型之保姆级讲解

目录前言一&#xff0c;面向对象编程1.1 面向过程与面向对象1.2 JS创建类和对象1.3 类的继承1.4 Super关键词1.5 几个注意点二&#xff0c;构造函数原型2.1 创建对象的三种方法2.2 静态成员和实例成员2.3 构造函数的弊端2.4 函数的共享-原型prototype2.5 对象原型___proto__2.6…

用Python制作你的专属音乐播放器(此刻浪漫只属于你哦*´▽`*)

文章目录前言一、项目介绍二、环境配置三、代码实战前言 昨天是博主的一位朋友生日&#xff0c;除了送上大大的红包&#xff0c;知道他喜欢听音乐&#xff0c;特意用代码给他写了一个 专属音乐播放器&#xff0c;今天把这个代码也开源送给所有粉丝哦。 一、项目介绍 我们常用…

Vue--》实现动画与过渡效果

目录 动画效果 过渡效果 第三方动画库 Vue封装的过渡与动画作用是在插入、更新或移除DOM元素时&#xff0c;在合适的时候给元素添加类名。 动画效果 操作css的trasition或animation&#xff0c;vue会给目标元素添加/移除特定的class&#xff0c;过渡的相关类名是&#xff1…

Spring项目中用了这种解耦模式,经理对我刮目相看

前言 不知道大家在项目中有没有遇到过这样的场景&#xff0c;根据传入的类型&#xff0c;调用接口不同的实现类或者说服务&#xff0c;比如根据文件的类型使用 CSV解析器或者JSON解析器&#xff0c;在调用的客户端一般都是用if else去做判断&#xff0c;比如类型等于JSON&…

【Spring6源码・IOC】Bean的实例化

上一节我们讲到《【Spring6源码・IOC】BeanDefinition的加载》&#xff0c;这一节我们来讲解一下Bean的实例化。 根据xml或注解加载完Bean的信息后&#xff0c;最终会通过反射来创建bean的对象。 invokeBeanFactoryPostProcessors()主要是加载BeanDefinition。 finishBeanFa…

MAC(m1)-VMWare Fusion安装CentOS7.9(续)

下载了CentOS8&#xff0c;优先安装CentOS8 默认的配置有点小, 可以根据自己需求进行自定义设置&#xff1a; 点击存储&#xff0c;会出现&#xff1a; 咱们是中国人&#xff0c;优先选择中文&#xff1a; 点击网络和主机名&#xff0c;配置网络&#xff1a; 打开网卡开关&…

找出给定数组中和是给定目标整数的两个整数,输出找到的两个整数下标

找出给定数组中和是给定目标整数的两个整数&#xff0c;输出找到的两个整数下标。 (本文获得CSDN质量评分【x】)【学习的细节是欢悦的历程】Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#xff0c;不仅仅…

Android---简易Snackbar

目录 Snackbar 简介 Snackbar 特性 完整Demo Snackbar 简介 Snackbar 是 Android5.0 新特性---Material Design 中的一个控件&#xff0c;用来代替 Toast。Snackbar 就是一个类似 Toast 的快速弹出消息提示的控件&#xff0c;手机上显示在底部&#xff0c;大屏幕设备显示在左…

Golang实现分布式锁

1. go实现分布式锁 通过 golang 实现一个简单的分布式锁&#xff0c;包括锁续约、重试机制、singleflght机制的使用 1.1 redis_lock.go package redis_lockimport ("context"_ "embed""errors""github.com/go-redis/redis/v9""…

Java Netty框架自建DNS代理服务器教程

前言 DNS协议作为着互联网客户端-服务器通信模式得第一关&#xff0c;在当下每天都有成千上亿上网记录产生得当今社会&#xff0c;其重要性自然不可言喻。在国内比较有名得DNS服务器有电信得114.114.114.114、阿里云得223.5.5.5&#xff0c;DNSPod得119.29.29.29&#xff0c;配…

【矩阵论】8. 常用矩阵总结——镜面阵,正定阵

8.4 镜面阵 法向量确定一个镜面 8.4.1 镜面阵的作用 对法向量 Aα−αA\alpha-\alphaAα−αA(Aα)A2ααA(A\alpha)A^2\alpha\alphaA(Aα)A2αα 对镜面上向量 AYYAYYAYY 8.4.2 镜面阵表示 AIn−2ααH∣α∣2,其中α(x1x2⋮xn)∈Cn,且α≠0AI_n-\frac{2\alpha\alpha^H}{\…

【实际开发02】- 同模块 - 单表 CRUD 代码 - 批量操作

目录 0. yml 配置 1. 账号 / 密码 等有概率变更的信息 推荐 动态配置 , 避免写死 1. entity 处理 ( 减少后续 insert/update 判空处理 ) 1. volidation.annotation 配合 Valid - 参数校验 2. Validated - ( 相较于 valid 更加严谨的校验 ) 1. Save / Status 2. Update /…

vue中使用axios

一、axios axios是一个基于Promise的网络请求库。既可以在node.js&#xff08;服务器端&#xff09;使用&#xff0c;也可以在浏览器端使用 1. 在node.js中使用的原生的http模块 2. 在浏览器中使用的XMLHttpRequest 二、vue中的使用方法 1. 安装&#xff1a;npm install axios…

二分查找及其扩展

目录 二分查找算法思想&#xff1a; 循环 递归 有多个与key相等数据的查询&#xff0c;找最左边与关键字相等的那个 找第一个大于key的元素的下标 有序循环数组的二分查找 二分查找算法思想&#xff1a; 二分查找也叫折半查找&#xff0c;查找效率较高。但是查找的线性表…

振弦采集模块电子标签测量(智能振弦传感器)

振弦采集模块电子标签测量&#xff08;智能振弦传感器&#xff09; 此功能在 SF3.52 版本时增加。 固件版本 V3.52 修改固件版本号为 V3.52_2201009。 增加了电子标签测量功能。 WKMOD.[12]用于控制是否使用此功能 新增状态位 STATUS.[13]&#xff0c;用来表示是否检测到了电子…