【数据结构与算法 刷题系列】求带环链表的入环节点(图文详解)

             💓 博客主页:倔强的石头的CSDN主页 

             📝Gitee主页:倔强的石头的gitee主页

   ⏩ 文章专栏:《数据结构与算法 经典例题》C语言

                                  期待您的关注

1b7335aca73b41609b7f05d1d366f476.gif

目录

一、问题描述

二、解题思路

方法一:数学公式推导法

方法二:转换为相交链表问题求解

三、代码实现

方法一实现代码

方法二实现代码


一、问题描述

原题链接   142. 环形链表 II - 力扣(Le142. 环形链表 II - 力扣(Le

二、解题思路

方法一:数学公式推导法

预备知识

此方法的数学推导建立在判断链表是否带环的基础算法上,推荐阅读前置文章

点击下方文字

【数据结构与算法 刷题系列】判断链表是否有环-CSDN博客

 如图,通过快慢指针法得到两个指针相遇位置时

假设:

  • 链表入环前的长度为L
  • 环的长度为C
  • 快慢指针相遇节点为meet
  • 环的入口与相遇节点meet的距离为N
  • 相遇时,快指针已经在环内走了X圈(X>=1,快指针至少比慢指针都走一圈才能追上)
推导过程:

在meet相遇点

慢指针移动距离为L+N

快指针移动距离为L+X*C+N

 

另外,快指针移动距离是快指针的两倍

快指针也可以写成2(L+N)

将两条公式结合起来

2(L+N)=L+X*C+N

化简

L+N=X*C

L=X*C-N

L=(X-1)*C+C-N    

 最终得到的公式:

L=(X-1)*C+C-N    

该公式在图中说明的问题:

链表入环前的长度L

与相遇点到环入口的距离再加(X-1)圈      ——X最少为1,所以X-1至少为0

是相等的

结论:

如果两个指针分别从链表起始位置和相遇点meet开始移动,那么两个指针第一次相遇的节点就是环的入口

方法二:转换为相交链表问题求解

此方法的数学推到建立在判断链表是否带环的基础算法上,推荐阅读

【数据结构与算法 刷题系列】相交链表-CSDN博客

该方法是将带环链表问题转换为相交链表问题,将问题降级处理

 首先,依然要 求得快慢指针相遇交点

然后将取得该节点下一个节点地址,令其成为一个单独链表的首节点,断开链表 

 之后,这个问题就可以转换为相交链表问题来解决

 

三、代码实现

方法一实现代码

struct ListNode {int val;struct ListNode* next;};
typedef struct ListNode ListNode;//方法一:数学推理法
struct ListNode* detectCycle1(struct ListNode* head)
{ListNode* slow, * fast;slow = fast = head;ListNode* meet = NULL;while (fast && fast->next){slow = slow->next;fast = fast->next->next;if (slow == fast)//先求得快慢指针相遇节点{meet = slow;while (meet != head)//两指针同时移动,相遇即是入口{meet = meet->next;head = head->next;}return meet;}}return NULL;
}

方法二实现代码

//求相交链表的交点的函数
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB)
{ListNode* pcurA = headA;ListNode* pcurB = headB;int countA = 0;int countB = 0;while (pcurA)//求出链表长度{pcurA = pcurA->next;countA++;}while (pcurB){pcurB = pcurB->next;countB++;}int tmp = abs(countA - countB);//长度差值ListNode* slow, * fast;if (countA < countB){slow = headA;fast = headB;}else{slow = headB;fast = headA;}while (tmp--)//长链表先走差值的步数{fast = fast->next;}while (fast && slow)//同步比较{if (fast == slow)return fast;fast = fast->next;slow = slow->next;}return NULL;
}
struct ListNode* detectCycle(struct ListNode* head)
{ListNode* slow, * fast;slow = fast = head;ListNode* meet = NULL;while (fast && fast->next){slow = slow->next;fast = fast->next->next;if (slow == fast)//先求得快慢指针相遇节点{meet = slow;ListNode* newhead = meet->next;meet->next = NULL;//将环断开,变成两个相交的链表return getIntersectionNode(head, newhead);}}return NULL;
}

总结

两种方法可以自行选用
第一种方法属于推理复杂,代码简单

第二种方法属于推理简单,代码实现细节复杂

可根据实际情况选择合适的方法

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

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

相关文章

LaTeX 的使用

文章目录 TeX 编辑器文档类型中文编译文档结构preamble 导言区&#xff08;不能放正文内容&#xff09;document body 正文区 正文内容目录段落列表无序列表有序列表 图片表格交叉引用段落图片表格 转义符 数学公式数学符号行内公式行间公式有公式计数器无公式计数器 公式包含文…

男生下班后的“秘密基地”——经典国产车T9为何适合你

随着都市生活的节奏加快&#xff0c;男生们在工作之余渴望有一片属于自己的宁静空间。越来越多的男生选择在下班后&#xff0c;不急于回家&#xff0c;而是在车里多呆一会儿。这个“秘密基地”不仅为他们提供了短暂的放松和逃离&#xff0c;更成为了一种生活态度的象征。今天&a…

k8s通过deployment创建pod失败排查

通过deployment创建pod失败 在k8s集群中&#xff0c;deployment启动后没有成功创建pod&#xff0c;通过“kubectl describe deployment ${DEPLOY_NAME} ”&#xff0c;看到如下日志&#xff0c;只看到“ReplicaFailure True FailedCreate”&#xff0c;但是没有failed的原因。 …

Python 全栈系列254 异步服务与并发调用

说明 发现对于异步(IO)还是太陌生了&#xff0c;熟悉一下。 内容 今天搞了一整天&#xff0c;感觉有一个long story to tell&#xff0c;但是不知道从何说起&#xff0c;哈哈。 异步(协程)需要保证链路上的所有环节都是异步(协程)的&#xff0c;任何一个环节没这么做都会导致…

YOLOv10涨点改进轻量化双卷积DualConv,完成涨点且计算量和参数量显著下降

本文独家改进:双卷积由组卷积和异构卷积组成,执行3x3 和 1x1 卷积运算Q代替其他卷积核仅执行 1x1 卷积。 DualIConv 显着降低了深度神经网络的计算成本和参数数量,同时在某些情况下令人惊讶地实现了比原始模型略高的精度。 我们使用 DualConv 将轻量级 MobileNetV2 的参数数量…

go 定时任务

在 Go 语言中&#xff0c;可以使用内置的 time 包来实现定时任务。以下是一个简单的示例&#xff1a; go package main import ( "fmt" "time" ) func main() { timer : time.NewTimer(2 * time.Second) <-timer.C fmt.Println(…

Linux驱动面试题

1.导出符号表的原理&#xff1f; 2.字符设备驱动的框架流程 open read wirte close 是系统调用&#xff08;从用户空间进入内核空间的唯一的方法&#xff09;会产生swi软中断《也会存在软中断号》&#xff08;从User模式切换到SVC&#xff08;管理模式&#xff09;下因为在…

Starknet架构之Starknet state、State commitment

文章目录 Starknet架构之Starknet state过渡到新状态Starknet架构之状态承诺State commitmentMerkle-Patricia trie 默克尔-帕特里夏树Starknet架构之Starknet state 原文链接: https://docs.starknet.io/architecture-and-concepts/network-architecture/starknet-state/ S…

你还不会选ProfiNET和EtherCAT网线?

在现代工业自动化领域&#xff0c;ProfiNET和EtherCAT是两种非常流行的通信协议。选择合适的网线对于确保通信的稳定性和效率至关重要。 ProfiNET是什么&#xff1f; ProfiNET是一种基于以太网的通信协议&#xff0c;由德国西门子公司开发。它支持实时通信&#xff0c;广泛应用…

Spring框架中的IOC(控制反转)详解

Spring框架中的IOC&#xff08;控制反转&#xff09;详解 一、引言 在软件开发中&#xff0c;设计模式与框架的应用极大地提高了开发效率和软件质量。其中&#xff0c;Spring框架因其强大的功能和灵活的扩展性&#xff0c;成为了Java企业级应用开发的首选。而Spring框架中的核…

商超智能守护:AI监控技术在零售安全中的应用

结合思通数科大模型的图像处理、图像识别、目标检测和知识图谱技术&#xff0c;以下是详细的商超合规监测应用场景描述&#xff1a; 1. 员工仪容仪表监测&#xff1a; 利用图像识别技术&#xff0c;系统可以自动检测员工是否按照规范整理妆容、穿着工作服&#xff0c;以及是否…

大学课设项目,Windows端基于UDP的网络聊天程序的服务端和客户端

文章目录 前言项目需求介绍一、服务端1.对Udp套接字进行一个封装2. UdpServer的编写3. Task.h4.protocol.h的编写5.线程池的编写6.main.cc 二、客户端1. Socket.h2.protocol.h3.UdpClient4.menu.h5.main.cpp 三、运行图 前言 本次项目可以作为之前内容的一个扩展&#xff0c;学…

Mac 终端报错 zsh: command not found: brew 解决方案

Homebrew安装 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"安装成功后&#xff0c;在终端输入下面命令 brew -v如果成功输出brew版本&#xff0c;则安装成功 关闭终端重新打开终端&#xff0c;报错zsh: comm…

003 gitee怎样将默认的私有仓库变成公开仓库

先点击“管理”&#xff0c; 再点击“基本信息” 在“是否开源”里&#xff0c; 选择&#xff1a;开源

python文件操作、文件操作、读写文件、写模式

with读取文件数据内容 with open(filepath,mode,encoding) as file:#具体操作,例如&#xff1a;print(file.read())#查看文件所有的内容。 with&#xff1a;Python中的一个上下文管理器&#xff0c;用于简化资源的管理和释放。它可以用于任意需要进行资源分配和释放的情境…

MySQL 保姆级教程(七):用正则表达式进行搜索

第 9 章 用正则表达式进行搜索 9.1 正则表达式介绍 正则表达式是用来匹配文本的特殊的串&#xff08;字符集合&#xff09; 9.2 使用 MySQL 正则表达式 MySQL 用WHERE 子句对正则表达式提供了初步的支持&#xff0c;允许你指定正则表达式&#xff0c;过滤 SELECT 检索出的数…

高级前端开发需要知道的 25 个 JavaScript 单行代码

1. 不使用临时变量来交换变量的值 例如我们想要将 a 于 b 的值交换 let a 1, b 2;// 交换值 [a, b] [b, a];// 结果: a 2, b 1 这行代码使用数组解构赋值的方式来交换两个变量的值&#xff0c;无需定义新的临时变量。这个巧妙的技巧可让代码看起来更简洁明了。语法[a, b]…

使用 Azure AI Document Intelligence 创建智能文档处理

简介 借助 Azure AI 文档智能中的预生成模型&#xff0c;无需自行训练模型&#xff0c;即可从常见表单和文档中提取数据。 公司中&#xff0c;表单种类繁多&#xff0c;如发票、收据、调查表等。你可能想知道&#xff0c;从这些文档中提取姓名、地址、金额等信息需要多少工作…

linux下C语言如何操作文件(五)

对(四)增加的函数编写测试代码。 static void file_oper_demo_01(const char* path){log_yellow("command: %s\n", path);String* str = build_string(path);char pspace[2] = { , \0};struct string_segment *cmds = str->split_by(str, pspace);if(cmds == NUL…

APaaS:智能制造助手

资金不足、IT基础架构薄弱...... 车间业务需求不断地在增加...... 都在说数字化&#xff0c;都在说转型...... 随着企业竞争的日益激烈和市场环境的快速变化&#xff0c;企业需要一个灵活、高效、快速响应市场变化的新平台。在这样的背景下&#xff0c;APaaS应运而生&#x…