Java环形链表(图文详解)

目录

一、判断链表中是否有环

(1)题目描述

(2)题解

二、环形链表的入环节点

(1)题目描述

(2)题解


一、判断链表中是否有环

(1)题目描述

给你一个链表的头节点 head ,判断链表中是否有环。

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

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

示例:

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

输出:true(节点有环)

(2)题解

思路分析:我们可以使用快慢指针来分析这个问题。

1.首先定义fast、slow指向head

2.快指针fast一次走两步、慢指针slow一次走一步

3.如果链表中无环,fast最终会指向null,若链表中有环,在fast和slow都进入环中后,由于fast每次比slow多走一步,fast最终会追上slow

代码实现:

public class Solution {public boolean hasCycle(ListNode head) {//先判断特殊情况//若链表中为空或链表中只有一个元素,// 则链表中无环// 直接返回falseif (head == null || head.next == null) {return false;}//定义快指针和慢指针ListNode fast = head;ListNode slow = head;while (fast != null && fast.next != null) {fast = fast.next.next;//fast一次走两步slow = slow.next;//slow一次走一步if (fast == slow) {//fast与slow相遇,表明链表带环return true;}}//fast指向空或指向尾节点,表明链表不带环return false;}
}

思考:

1. while条件中,能否修改为 while(fast.next != null && fast != null) ?

不能,&&(逻辑与)操作符从左到右进行判断,当左边为false时,右边的表达式不会进行运算,直接返回false,只有当左边表达式为true时,才会运算右边的表达式,若右边表达式为true,则返回true

在while条件中,应先判断fast的指向是否为空,若fast的指向为空,则不能够通过fast.next访问下一个节点,否则会抛出NullPointerException(空指针异常)。因此,while (fast != null && fast.next != null),当fast指向null时,直接返回false,而不再执行fast.next

2. 当fast走两步,slow走一步时,fast能够追上slow,当fast走三步、四步...时能否追上slow ?

当链表无环时,fast走两步、三步...都能判断链表无环

当链表有环时,我们假设fast每次走 x ( x >= 2 )步,head到入环节点有a个节点(从head到入环节点需要走a步),环上一共有C个节点,当slow走到入环节点时,fast与slow相距N0 <= N < C)个节点

当N = 0时,fast与slow直接在入环节点相遇,因此我们考虑N > 0 且 N < C 的情况

当slow走到入环节点时,此时就是我们常说的追及问题,追及问题的公式:

追及时间(次数) = 路程差 / 速度差

我们设追及次数(即fast走多少次追上slow)为m,fast与slow之间的路程差为N,速度差为x-1,则m = N / x-1,

当x = 2时,m = N,即fast走N次就能追上slow,

当x = 3时,m = N / 2,当N为偶数时,fast 走N/2次能够追上slow;当N为奇数时,fast走了(N-1)/ 2次之后,此时fast与slow的距离为1,由于fast走三步,slow走一步,fast会反超slow 1 步

此时fast与slow的距离N变为C-1,fast重新开始追及slow,若C-1为偶数,则经过 (C-1)/2次后,fast追上slow;若C-1为奇数,在fast与slow距离为1时,fast再次反超slow,fast与slow之间的距离再次变为C-1,fast再次追及slow...如此循环,fast永远追不上slow

 因此,我们可以看出,当fast一次走三步,slow一次走一步时,fast不一定能追上slow

当fast一次走四步,slow一次走一步时,分析思路与fast一次走三步一致,fast可能反超slow一步或两步,此时fast与slow的距离变为C-1 或 C-2,然后继续分情况分析

3.当fast走三步,slow走两步,或是fast走四步,slow走三步时,情况又如何呢 ?

由追及时间(次数) = 路程差 / 速度差,可以得出

当fast走三步,slow走两步 或是 fast一次走四步,slow一次走三步,fast与slow的速度差都为1,fast一定能追上slow,但

当fast一次走两步,slow一次走一步,slow走的总路程为N,即fast在一圈以内,能够追上slow

而当fast一次走三步,slow一次走两步时,slow走的总路程为2*N(2*N可能大于C),因此fast不一定在一圈之内追上slow

本题来自:

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

二、环形链表的入环节点

(1)题目描述

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

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

示例

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

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

(2)题解

思路分析:在判断链表是否有环中,我们使用快慢指针的方法来判断链表中是否有环。fast一次走两步,slow一次走一步,若链表有环,fast一定能在环中追上slow。基于这个结论,我们可以继续推出另一个结论:从头节点出发的指针会和从fast、slow相遇节点出发的指针相遇与入环节点(证明在最后)

因此,找到入环节点:

1.判断链表是否有环,无环返回null,有环找到fast与slow相遇的节点

2.让两个指针,分别从头节点、相遇点出发,当两指针汇合时,即为链表的入环节点

代码实现:

public class Solution {public ListNode detectCycle(ListNode head) {//链表为空,直接返回nullif(head == null){return null;}ListNode fast = head;ListNode slow = head;while(fast.next != null && fast.next.next != null){fast = fast.next.next;slow = slow.next;//找到fast与slow的相遇点if(fast == slow){//让fast从头节点出发,//slow从相遇点出发,fast = head;while(fast != slow){fast = fast.next;slow = slow.next;}//相遇节点即为入环节点return slow;}}//链表中无环,返回nullreturn null;}
}

为何从头节点出发的指针一定会和从fast、slow相遇节点出发的指针汇合与入环节点?

同样,当链表有环时,我们假设head到入环节点有a个节点(从head到入环节点需要走a步),环上一共有C个节点,fast与slow相遇时,与入环节点的距离为d

当fast与slow相遇时,

fast所走的路程为 a + n*C + d

fast所走路程为什么是a + n*C + d?

a为从头节点到入环节点的距离,当a > C时,可能slow还未进环,而fast已经在环中走了很多圈了,我们假设当fast与slow相遇时,fast在环中走了n圈,因此fast所走的路程为a + n*C + d

slow所走的路程为 a + d

由于fast的速度是slow的两倍,因此

2*(a + d)= a + n*C + d,即 a = n*C - d

将n*C化为 C*(n-1) + C,式子可化为 a =C* (n-1) + C-d

a是从头节点到入环节点的距离,C - d 是 相遇节点距入环节点的距离,

a =C* (n-1) + n-d 表明,从头节点出发的指针走 a步 等于 从相遇节点开始走的指针,走(n-1)圈后回到相遇点,再走n - d的距离,即从头节点出发的指针和从fast、slow相遇节点同时出发的指针最终会在入环节点处相遇

题目来自:

142. 环形链表 II - 力扣(LeetCode)

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

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

相关文章

构建智能客服知识库,优化客户体验不是难题!

在当今快节奏的商业环境中&#xff0c;客户都希望得到及时个性化的支持&#xff0c;拥有一个智能客服知识库对于现代企业至关重要。智能客服知识库是一个集中存储、组织和访问与客户服务互动相关的信息的综合性知识库。它为企业提供了全面的知识来源&#xff0c;使他们能够为客…

想要精通算法和SQL的成长之路 - 最长递增子序列 II(线段树的运用)

想要精通算法和SQL的成长之路 - 最长递增子序列 II&#xff08;线段树的运用&#xff09; 前言一. 最长递增子序列 II1.1 向下递推1.2 向上递推1.3 更新操作1.4 查询操作1.5 完整代码&#xff1a; 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 最长递增子序列 II 原题链接…

单链表详细解析|画图理解

前言&#xff1a; 在前面我们学习了顺序表&#xff0c;相当于数据结构的凉菜&#xff0c;今天我们正式开始数据结构的硬菜了&#xff0c;那就是链表&#xff0c;链表有多种结构&#xff0c;但我们实际中最常用的还是无头单向非循环链表和带头双向循环链表&#xff0c;我们今天先…

idea没有maven工具栏解决方法

背景&#xff1a;接手的一些旧项目&#xff0c;有pom文件&#xff0c;但是用idea打开的时候&#xff0c;没有认为是maven文件&#xff0c;所以没有maven工具栏&#xff0c;不能进行重新加载pom文件中的依赖。 解决方法&#xff1a;选中pom.xml文件&#xff0c;右键 选择添加为…

Denoising diffusion implicit models 阅读笔记

Denoising diffusion probabilistic models (DDPMs)从马尔科夫链中采样生成样本&#xff0c;需要迭代多次&#xff0c;速度较慢。Denoising diffusion implicit models (DDIMs)的提出是为了加速采样过程&#xff0c;减少迭代的次数&#xff0c;并且要求DDIM可以复用DDPM训练的网…

计算机网络补充

未分类文档 CDMA是码分多路复用技术 和CMSA不是一个东西 UPD是只确保发送 但是接收端收到之后(使用检验和校验 除了检验的部分相加 对比检验和是否相等。如果不相同就丢弃。 复用和分用是发生在上层和下层的问题。通过比如时分多路复用 频分多路复用等。TCP IP 应用层的IO多路…

绿色计算产业发展白皮书:2022年OceanBase助力蚂蚁集团减排4392tCO2e

9 月 15 日&#xff0c;绿色计算产业联盟在 2023 世界计算大会期间重磅发布了《绿色计算产业发展白皮书&#xff08;2023 版&#xff09;》。蚂蚁集团作为指导单位之一&#xff0c;联合参与了该白皮书的撰写。 白皮书中指出&#xff0c;落实“双碳”战略&#xff0c;绿色计算已…

基于微信小程序的场地预约系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言系统主要功能&#xff1a;具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计…

亮相“外滩金融峰会” 百望云实力入选“融城杯金融科技创新十佳案例”

近日&#xff0c;第五届“外滩金融峰会”在上海召开&#xff0c;百望云受邀出席峰会&#xff0c;与全球财经政要、机构高管与学界领袖齐聚外滩&#xff0c;分享真知灼见&#xff0c;以对话推动共识。 本届峰会由中国金融四十人论坛&#xff08;CF40&#xff09;与中国国际经济交…

electron之快速上手

前一篇文章已经介绍了如何创建一个electron项目&#xff0c;没有看过的小伙伴可以去实操一下。 接下来给大家介绍一下electron项目的架构是什么样的。 electron之快速上手 electron项目一般有两个进程&#xff1a;主进程和渲染进程。 主进程&#xff1a;整个项目的唯一入口&…

HashMap 源码解读(JDK1.8)

一、HashMap说明 基于哈希表的 Map 接口实现。此实现提供所有可选的map操作&#xff0c;并允许空值和空键。&#xff08;HashMap 类大致等同于 Hashtable&#xff0c;只是它不支持同步并且允许空值。&#xff09;此类不保证插入键值的顺序&#xff1b;特别是&#xff0c;它不保…

Mendix中的依赖管理:npm和Maven的应用

序言 在传统java开发项目中&#xff0c;我们可以利用maven来管理jar包依赖&#xff0c;但在mendix项目开发Custom Java Action时&#xff0c;由于目录结构有一些差异&#xff0c;我们需要自行配置。同样的&#xff0c;在mendix项目开发Custom JavaScript Action时&#xff0c;…

48v转24v 3A 48v转12v 48v转5v电源芯片AH7691X

AH7691X是一款高-效-率、高-压降压型DC-DC转换器&#xff0c;采用固定110KHz的开关频率&#xff0c;具备3A的输出电流能力&#xff0c;低纹波&#xff0c;并且具备***软启动功能、过压保护功能和温度保护。该器件还集成了峰值限流功能&#xff0c;简化了电路设计。 AH7691X内部…

MFC 绘图

效果图&#xff1a;三张bmp图 字 竖线 组成 在OnPaint()函数中 CPaintDC dc(this);CRect rect;GetClientRect(&rect); //获取客户区矩形CDC dcBmp; //定义并创建一个内存设备环境dcBmp.CreateCompatibleDC(&dc); //创建兼容性DCCBitmap …

【kafka实战】01 3分钟在Linux上安装kafka

本节采用docker安装Kafka。采用的是bitnami的镜像。Bitnami是一个提供各种流行应用的Docker镜像和软件包的公司。采用docker的方式3分钟就可以把我们想安装的程序运行起来&#xff0c;不得不说真的很方便啊&#xff0c;好了&#xff0c;开搞。使用前提&#xff1a;Linux虚拟机&…

AKKA 互相调用

SpringBoot 集成 AKKA 可以参考此文&#xff1a;SpringBoot 集成 AKKA 场景1&#xff1a;bossActor 收到信息&#xff0c;然后发给 worker1Actor 和 worker2Actor controller 入口&#xff0c;初次调用 ActorRef.noSender() Tag(name "test") RestController Req…

【MATLAB第77期】基于MATLAB代理模型算法的降维/特征排序/数据处理回归/分类问题MATLAB代码实现【更新中】

【MATLAB第77期】基于MATLAB代理模型算法的降维/特征排序/数据处理回归/分类问题MATLAB代码实现 本文介绍基于libsvm代理模型算法的特征排序方法合集&#xff0c;包括&#xff1a; 1.基于每个特征预测精度进行排序&#xff08;libsvm代理模型&#xff09; 2.基于相关系数corr的…

前端技术社区总目录

前端技术社区欢迎您的订阅。订阅后&#xff0c;您将可以查看以下所有博客内容。 注&#xff1a;专栏内容主要面向新手 注&#xff1a;每个示例都有相对应的完整代码 注&#xff1a;该专栏博客内容将会逐步迁移至https://blog.csdn.net/m0_60387551/article/details/128017725 …

用于自然语言处理的 Python:理解文本数据

一、说明 Python是一种功能强大的编程语言&#xff0c;在自然语言处理&#xff08;NLP&#xff09;领域获得了极大的普及。凭借其丰富的库集&#xff0c;Python 为处理和分析文本数据提供了一个全面的生态系统。在本文中&#xff0c;我们将介绍 Python for NLP 的一些基础知识&…

Sound/播放提示音, Haptics/触觉反馈, LocalNotification/本地通知 的使用

1. Sound 播放提示音 1.1 音频文件: tada.mp3&#xff0c; badum.mp3 1.2 文件位置截图: 1.3 实现 import AVKit/// 音频管理器 class SoundManager{// 单例对象 Singletonstatic let instance SoundManager()// 音频播放var player: AVAudioPlayer?enum SoundOption: Stri…