【C】链表算法题7 -- 环形链表||

leetcode链接https://leetcode.cn/problems/linked-list-cycle-ii/description/


问题描述 

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


示例1

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。


示例2

输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点


思路

  这道题可以沿用上一个环形链表的思想(快慢指针法),上一篇文章中证明了如果链表中有环,那么 fast 指针与 slow 指针一定可以在环中相遇,而在有环链表中还有一个结论,那就是相遇节点与头节点每次都走一步,他们必然会在入环处相遇(证明在代码之后)。

  有了这个结论之后,这道题就很好解决了,我们只需要先判断链表是否有环(上一个环形链表算法题),如果没有环,那么就返回NULL;如果有环,那么找到相遇节点 interNode 之后,然后定义一个节点指针 pcur 指向头节点,如果 pcur 与 interNode 不相同,那么就让 pcur 与interNode 同时往后走,直到他们两相等为止,入环的第一个节点即为 pcur


代码1

 typedef struct ListNode ListNode;//相交结点ListNode* IntersectionNode(ListNode* head){ListNode* slow = head, * fast = head;while (fast && fast->next){slow = slow->next;fast = fast->next->next;if (slow == fast){return slow;}}return NULL;}//入环的第一个节点
struct ListNode *detectCycle(struct ListNode *head) 
{//先找相交节点ListNode* interNode = IntersectionNode(head);if (interNode == NULL){return NULL;}//相遇节点与首结点每次走一步可以在入环处相遇ListNode* pcur = head;while (pcur != interNode){interNode = interNode->next;pcur = pcur->next;}return interNode;
}

 代码2

  当然,上述代码还可以改进一下。不难发现,其实 fast 与 slow 相遇之后,interNode 就是 slow (fast 也可以),所以可以直接用 slow 来作为相遇节点。

typedef struct ListNode ListNode;
struct ListNode *detectCycle(struct ListNode *head) 
{ListNode* fast = head, *slow = head;while (fast && fast->next){slow = slow->next;fast = fast->next->next;if (fast == slow){//相遇了,说明有环ListNode* pcur = head;while (pcur != slow){//相遇节点与首结点每次走一步可以在入环处相遇pcur = pcur->next;slow = slow->next;}return slow;}}return NULL;
}

证明 

  这里将链表抽象为以下结构(假设fast一次走两步,slow一次走一步):

设头节点为H,入环的第一个节点为E,fast 与 slow 相遇节点为M,H 到 E 距离为 L,E 到 M 距离为 X,环的周长为 R,所以 E 到 M 的距离就是 R - X ,再假设 fast 与 slow 相遇之前,fast 已经在环内走了 n 圈了,所以在相遇之前, fast 所走过的路程为:L + nR + X;而 slow 所走过的路程为:L + X,为什么 slow 没有绕环呢,因为在 slow 进入环后,fast 与 slow 的距离是越来越近的,他们俩的最大距离就是环的距离,而他们之间的距离又是越来越近的,所以 fast 是会在 slow 进入环之后的一圈内必然是会追上 slow 的。

  由于 fast 一次走两步,slow 一次走一步,所以 fast 所走的路程是 slow 所成路程的两倍,所以有如下这个等式:

  L + nR + X  = 2 * (L +X)

移项就可以得到:

  nR = L + X    =>   L = nR - X    =>    L =  (n - 1)R + R - X

这个等式也就表明,当 slow 到达相遇节点 M 之后,再绕环走 n - 1 圈,头节点也就到达了与 E 相距 R - X 的节点处;此时,slow 回到相遇点,与 E 的距离也是 R - X。所以相遇节点与头节点每次都走一步,他们必然会在入环处相遇。

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

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

相关文章

uniapp开发h5部署到服务器

1.发行>网站-PC Web或手机H5(仅适用于uniapp) 2.填写网站域名 3.编译成功后会生成一个unpackage文件夹找到下面的h5 4.接下来会使用一个工具把h5里面的文件放到服务器上面(WinSCP使用其他能部署的工具也行) 5.登录 6.登录成功后…

PyTorch Lightning Trainer介绍

PyTorch Lightning 的 Trainer 是框架的核心类,负责自动化训练流程、分布式训练、日志记录、模型保存等复杂操作。通过配置参数即可快速实现高效训练,无需手动编写循环代码。以下是详细介绍和使用示例: Trainer 的核心功能 自动化训练循环 自…

亚信安全正式接入DeepSeek

亚信安全致力于“数据驱动、AI原生”战略,早在2024年5月,推出了“信立方”安全大模型、安全MaaS平台和一系列安全智能体,为网络安全运营、网络安全检测提供AI技术能力。自2024年12月DeepSeek-V3发布以来,亚信安全人工智能实验室利…

小白零基础如何搭建CNN

1.卷积层 在PyTorch中针对卷积操作的对象和使用的场景不同,如有1维卷积、2维卷积、 3维卷积与转置卷积(可以简单理解为卷积操作的逆操作),但它们的使用方法比较相似,都可以从torch.nn模块中调用,需要调用的…

视频基础操作

1.1. 例子 读取mp4格式的视频,将每一帧改为灰度图,并且打上水印(“WaterMark”),并将其输出保存为out.mp4,在这个例子中可以看到视频读取,每帧数据处理,视频保存的整体流程简单示例 import cv…

21vue3实战-----git husky和git commit规范

21vue3实战-----git husky和git commit规范 1.husky工具1.1目的1.2如何做到这一点?1.3步骤 2.git commit规范2.1使用Commitizen自动生成规范格式供选择2.2代码提交风格2.3代码提交验证 之前在https://blog.csdn.net/fageaaa/article/details/145474065文章中已经讲了在vue项目…

Unity3D 类MOBA角色控制器 开箱即用

Github: Unity3D-MOBA-Character-Controller 觉得好用麻烦点个Star感谢!

Kafka 的消费offset原来是使用ZK管理,现在新版本是怎么管理的?

目录 基于 ZooKeeper 管理消费 offset 原理 缺点 新版本基于内部主题管理消费 offset 原理 优点 示例代码(Java) 在 Kafka 早期版本中,消费者的消费偏移量(offset)是存储在 ZooKeeper 中的,但由于 ZooKeeper 并不适合高频读写操作,从 Kafka 0.9 版本开始,消费偏…

使用 Nginx 搭建代理服务器(正向代理 HTTPS 网站)指南

在网络应用中,代理服务器是用于中转用户请求和服务端响应的工具。正向代理主要用于客户端与外部服务器之间的访问代理,帮助客户端隐藏其 IP 地址或访问受限资源。本文将详细介绍如何使用 Nginx 搭建正向代理服务器,特别是针对 HTTPS 网站的代…

arduino扩展:Arduino Mega 控制 32 个舵机(参考表情机器人)

参考:表情机器人中使用22个舵机的案例 引言 在电子制作与自动化控制领域,Arduino 凭借其易用性和强大的扩展性备受青睐。Arduino Mega 作为其中功能较为强大的一款开发板,具备丰富的引脚资源,能够实现复杂的控制任务。舵机作为常…

PyQt学习记录03——批量设置水印

0. 目录 PyQt学习记录01——加法计算器 PyQt学习记录02——串口助手 1. 前言 本次主要是为了学习Qt中的 QFileDialog 函数, QFileDialog.getExistingDirectory:用于选择文件夹,返回的是一个文件夹路径。 QFileDialog.getOpenFileName&…

Visual Studio 使用 “Ctrl + /”键设置注释和取消注释

问题:在默认的Visual Studio中,选择单行代码后,按下Ctrl /键会将代码注释掉,但再次按下Ctrl /键时,会进行双重注释,这不是我们想要的。 实现效果:当按下Ctrl /键会将代码注释掉,…

社区版IDEA中配置TomCat(详细版)

文章目录 1、下载Smart TomCat2、配置TomCat3、运行代码 1、下载Smart TomCat 由于小编的是社区版,没有自带的tomcat server,所以在设置的插件里面搜索,安装第一个(注意:安装时一定要关闭外网,小编因为这个…

利用kali linux 进行自动化渗透测试

本方案旨在自动化创建渗透测试全流程 一、架构 1.智能信息收集体系 class IntelligentOSINT:def __init__(self, target):self.target targetself.intelligence_sources [OSINT_Platforms,DeepWeb_Crawlers, SocialMedia_Trackers,ML_Correlation_Engine]def advanced_col…

Flink-DataStream API

一、什么样的数据可以用于流式传输 Flink的DataStream API 允许流式传输他们可以序列化的任何内容。Flink自己的序列化程序用于 基本类型:即字符串、长、整数、布尔值、数组复合类型:元组、POJO和Scala样例类 基本类型我们已经很熟悉了,下…

渗透利器:Burp Suite 联动 XRAY 图形化工具.(主动扫描+被动扫描)

Burp Suite 联动 XRAY 图形化工具.(主动扫描被动扫描) Burp Suite 和 Xray 联合使用,能够将 Burp 的强大流量拦截与修改功能,与 Xray 的高效漏洞检测能力相结合,实现更全面、高效的网络安全测试,同时提升漏…

AI时代,职场人如何开启学习之旅

为什么要学习 AI 在当今数字化时代,AI 正以前所未有的速度改变着我们的工作和生活方式。从智能客服到自动化生产,从数据分析到个性化推荐,AI 已经广泛渗透到各个行业和领域。学习 AI,对于工作人员来说,不仅是提升工作…

2.3 Transformer架构革命:从自注意力到万亿参数大模型的演进之路

Transformer架构革命:从自注意力到万亿参数大模型的演进之路 一、Transformer核心突破:彻底颠覆序列建模范式 1.1 传统序列模型的致命瓶颈 # RNN/LSTM的串行计算缺陷示例 hidden_state torch.zeros(seq_len, batch_size, hidden_dim) for t in ra…

Java 大视界 -- 深入剖析 Java 在大数据内存管理中的优化策略(49)

💖💖💖亲爱的朋友们,热烈欢迎你们来到 青云交的博客!能与你们在此邂逅,我满心欢喜,深感无比荣幸。在这个瞬息万变的时代,我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

JVM ②-双亲委派模型 || 垃圾回收GC

这里是Themberfue 在上节课对内存区域划分以及类加载的过程有了简单的了解后,我们再了解其他两个较为重要的机制,这些都是面试中常考的知识点,有必要的话建议背出来,当然不是死记硬背,而是要有理解的背~~~如果对 JVM …