当前位置: 首页 > news >正文

C++代码随想录刷题知识分享-----142.环形链表II

1. 题目要求

给定一个链表的头节点  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) 空间解决此题

    2. 算法思想 —— 快慢指针 Floyd 判环算法

    🧠 思路拆解:

    1. 第一阶段:判断是否有环

      • 设置两个指针:slow 每次走一步,fast 每次走两步。
      • fast 在某一时刻追上 slowslow == fast),说明链表有环。
      • 否则,fastfast->next 先到 nullptr,说明无环。
    2. 第二阶段:寻找环的入口节点

      • 新建一个指针 cur 从链表头开始。
      • curslow 每次都走一步,最终会在环的起点相遇。

    3. 完整注释版代码

    class Solution {
    public:ListNode *detectCycle(ListNode *head) {ListNode* slow = head;ListNode* fast = head;// 第一阶段:先判断链表是否有环(快慢指针)while (fast != nullptr && fast->next != nullptr) {slow = slow->next;           // 慢指针走一步fast = fast->next->next;     // 快指针走两步if (slow == fast) {          // 有环,找到相遇点// 第二阶段:从 head 和相遇点出发,再次相遇即为入环点ListNode* cur = head;while (cur != slow) {cur = cur->next;slow = slow->next;}return cur;              // 入环起点}}return nullptr; // fast 跑到了 null,无环}
    };
    

    4. 为什么相遇点到入环点距离 = 头到入环点距离?

    4.1. 变量定义(统一符号)

    • L:head 到入环点的距离(非环部分长度)
    • C:环的总长度(环的周长)
    • x:入环点到相遇点的距离(顺时针方向)
    • k:快指针比慢指针多绕的圈数
    • m:慢指针从入环点走到相遇点时走的距离,即 x
    • D:从相遇点再走 C - x 就是回到入环点的距离

    4.2. 数学推导(核心逻辑)

    设快慢指针在某个时刻第一次相遇:

    • 慢指针走了:L + x
    • 快指针走了:L + x + k * C(因为比慢指针多走 k 圈环)

    因为快指针每次走 2 步,慢指针走 1 步,所以:

    2(L + x) = L + x + kC
    

    化简得:

    L + x = kC   →   L = kC - x
    

    🔥 结论来了:

    相遇点再走 C - x会到入环点
    head 走 L = kC - x也会到入环点

    所以:

    一个指针从 head 出发,一个从相遇点出发,每次走一步,它们会在入环点相遇。


    🔁 3. 图形辅助理解

    链表结构如下( 表示 next):

    head → ... → (入环点) → a → b → c → ... → x↑            ↓←←←←←←←←←←←←←←
    

    设相遇发生在环中的节点 x,从入环点到 x 走了 x 步。
    你从 head 出发到达入环点,也走了 kC - x 步。

    • 慢指针再走 C - x 就回到入环点;
    • 而从 head 出发刚好也走了 kC - x 步;
    • 两者同时走,都会在入环点碰面。

    🧪 4. 举个例子

    假设链表如下:

    head → A → B → C → D → E → → → →↑       ↓H ← G ← F
    
    • 入环点是:E
    • 环:E → F → G → H → E(长度 C = 4
    • 假设快慢指针第一次相遇在 G,即入环点 E 到相遇点 G 的距离是 x = 2
    • 则:
      • L = kC - x = 1×4 - 2 = 2
      • 也就是说,从 head 到 E 有两步
      • G 再走 C - x = 2 步也回到 E
    • 两者同时走,都会在 E 相遇 

    根据 Floyd 判环算法推导,在第一次相遇后,从头节点和相遇点各起一指针,每次一步,它们将同时在入环点相遇

    原因是:
    相遇前慢指针走了 L + x,快指针走了 L + x + kC,由快慢速比得出:
    2(L + x) = L + x + kC → L = kC - x,即从 head 到入环点的距离等于从相遇点到入环点的距离。
    所以两个指针每次走一步,最终会同步到达入环点。


    5. 时间与空间复杂度

    指标复杂度
    时间复杂度O(n) 最多遍历两次链表
    空间复杂度O(1) 不使用额外数据结构

    6. 扩展面试题 & 必会变体

    问题解法提示
    如何判断链表是否有环?Floyd 判环算法
    如何找出环的起始点?相遇后双指针同步走
    环的长度是多少?相遇后在环中走一圈计数
    如果链表有交点 + 有环怎么办?必须分环内交点、环前交点、多环链表等情况分析

    7. 小结

    知识点一句话记忆
    Floyd 判环快慢指针相遇即有环
    入环点求法相遇后设新指针从 head 出发,与 slow 同步走
    空间优化不使用哈希表,仅用指针操作
    不允许修改链表结构所以不能破坏 next 指针或用标记法

    相关文章:

  • C++智能指针简介
  • Dagster中的Ops与Assets:数据管道构建的两种选择
  • C语言中的自定义类型 —— 结构体.位段.联合体和枚举
  • 深入理解Redis SDS:高性能字符串的终极设计指南
  • 用PyTorch搭建卷积神经网络实现MNIST手写数字识别
  • 《ATPL地面培训教材13:飞行原理》——第3章:基础空气动力学理论
  • 广义线性模型三剑客:线性回归、逻辑回归与Softmax分类的统一视角
  • 【查看.ipynp 文件】
  • 文献总结:TPAMI端到端自动驾驶综述——End-to-End Autonomous Driving: Challenges and Frontiers
  • 基于Springboot+Mysql的校园博客系统(含LW+PPT+源码+系统演示视频+安装说明)
  • 信息安全导论:解码社会工程学攻击的隐形战争
  • 【PostgreSQL数据分析实战:从数据清洗到可视化全流程】1.1 数据库核心概念与PostgreSQL技术优势
  • 软件工程实践
  • 基于 Dify + vLLM插件 + Qwen3 构建问答机器人Docker版
  • 机器人--MCU
  • MySQL数据操作全攻略:DML增删改与DQL高级查询实战指南
  • Oracle RAC ‘Metrics Global Cache Blocks Lost‘告警解决处理
  • 火语言RPA--DestoonV8商品发布
  • Qt 中实现观察者模式(Observer Pattern)
  • ros2 humble 控制真实机械臂(以lerobot为例)
  • 江苏淮安优化村级资源配置:淮安区多个空心村拟并入邻村
  • 无人机穿越大理崇圣寺千年古塔时“炸机”,当地:肇事者已找到,将被追责
  • 美CIA发布视频“招募中国官员窃取机密”,外交部:赤裸裸的政治挑衅
  • 马克思主义理论研究教学名师系列访谈|石书臣:思政课是落实立德树人的关键
  • 媒体评特朗普对进口电影征100%关税:让好莱坞时代加速谢幕
  • 抗战回望18︱《广西学生军》:“广西的政治基础是青年”