解密链表环的起点:LeetCode 142 题

解密链表环的起点:LeetCode 142 题

解密链表环的起点:LeetCode 142 题

视频地址

因为想更好的为大佬服务,制作了同步视频,这是Bilibili的视频地址

🌟 引言

链表环检测问题在C++中同样是一个经典面试题。本文将用C++实现LeetCode 142题"环形链表II"的解决方案,深入讲解快慢指针算法的原理和实现细节。

🔍 问题描述

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

🧠 解题思路回顾

快慢指针算法

  1. 使用两个指针:slow每次走一步,fast每次走两步
  2. 如果两指针相遇,说明链表有环
  3. 将其中一个指针重置到链表头,然后两指针以相同速度前进
  4. 再次相遇的位置就是环的起点

数学原理

设:

  • 链表头到环起点距离:a
  • 环起点到相遇点距离:b
  • 相遇点到环起点距离:c

则有:

  • 第一次相遇时:slow走了a+bfast走了a+b+c+b
  • 因为fast速度是slow的两倍:2(a+b) = a+2b+c
  • 推导得:a = c

💻 C++代码实现

/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */classSolution{public: ListNode *detectCycle(ListNode *head){// 边界条件处理if(head ==nullptr|| head->next ==nullptr){returnnullptr;} ListNode *slow = head; ListNode *fast = head;// 第一阶段:检测是否有环while(fast !=nullptr&& fast->next !=nullptr){ slow = slow->next; fast = fast->next->next;if(slow == fast){break;// 相遇说明有环}}// 检查是否因为无环退出循环if(fast ==nullptr|| fast->next ==nullptr){returnnullptr;}// 第二阶段:寻找环起点 slow = head;// 重置慢指针到头部while(slow != fast){ slow = slow->next; fast = fast->next;}return slow;// 相遇点即为环起点}};

🛠 代码解析

数据结构定义

structListNode{int val; ListNode *next;ListNode(int x):val(x),next(NULL){}};

这是LeetCode标准的链表节点定义,包含一个整数值和指向下一个节点的指针。

算法实现细节

寻找环起点

slow = head;// 重置慢指针到头部while(slow != fast){ slow = slow->next; fast = fast->next;}

根据数学推导,两指针以相同速度前进,再次相遇点即为环起点。

无环检查

if(fast ==nullptr|| fast->next ==nullptr){returnnullptr;}

如果因为快指针无法前进而退出循环,说明无环。

环检测阶段

while(fast !=nullptr&& fast->next !=nullptr){ slow = slow->next; fast = fast->next->next;if(slow == fast){break;// 相遇说明有环}}

快指针每次走两步,慢指针每次走一步,直到相遇或快指针无法前进。

指针初始化

ListNode *slow = head; ListNode *fast = head;

快慢指针都从头节点开始。

边界条件处理

if(head ==nullptr|| head->next ==nullptr){returnnullptr;}

处理空链表或单节点链表的特殊情况。

🚀 性能分析

  • 时间复杂度:O(n)
    • 最坏情况下需要遍历链表两次
  • 空间复杂度:O(1)
    • 只使用了固定数量的指针变量

🐞 常见问题与调试

常见错误

  1. 初始条件处理
    忘记处理空链表或单节点链表的情况。
  2. 指针重置错误
    在第二阶段错误地重置了快指针而不是慢指针。

空指针访问

while(fast !=nullptr&& fast->next !=nullptr)

必须同时检查fastfast->next,否则可能访问空指针的next成员。

调试技巧

  1. 小规模测试
    • 无环链表:1->2->3->null
    • 有环链表:1->2->3->4->2(环在节点2)
  2. 边界测试
    • 空链表
    • 单节点自环链表
    • 双节点互相指向的链表

打印指针地址

cout <<"Slow: "<< slow <<" Fast: "<< fast << endl;

帮助跟踪指针移动情况。

📊 复杂度对比表

方法时间复杂度空间复杂度适用场景
哈希表法O(n)O(n)需要简单实现时
快慢指针O(n)O(1)需要节省空间时

🌈 总结

通过C++实现的快慢指针算法,我们能够高效地解决链表环检测问题。关键在于:

  1. 理解快慢指针相遇的数学原理
  2. 正确处理边界条件和指针访问

分两个阶段实现:环检测和环起点定位

解密链表环的起点:LeetCode 142 题

这种方法不仅高效(O(n)时间,O(1)空间),而且体现了算法设计的巧妙之处。掌握这个技巧,你就能轻松应对链表相关的各种环检测问题了!

Read more

B站PC端web自动开启字幕脚本(2025新版适配)

B站自动字幕用户脚本:快捷键开关 + 自动开启字幕(2026新版适配) 作者:Apixus 更新日期:2026年3月5日 项目地址:GitHub仓库 一、脚本介绍 你是否经常在B站看视频时反复手动开启字幕?是否希望切换视频时字幕能自动开启? 这个用户脚本就是为了解决这些问题而开发的。 B站自动字幕脚本 提供了以下功能: * 🎯 快捷键控制:按 C 键快速开启或关闭字幕 * 🔄 自动开启:切换分P、点击推荐视频时自动打开字幕 * 🆕  2026新版适配:专为B站最新版播放器优化 * ⚡ 性能优化:智能监听,告别卡顿轮询 * 🛡️ 防冲突:自动识别输入框,避免误触 二、适用页面 * 普通视频页:https://www.bilibili.com/video/* * 播放列表页:https://www.bilibili.com/list/* 支持普通视频页、番剧页、播放列表页等常见场景。 三、

By Ne0inhk
JVM 可达性分析算法

JVM 可达性分析算法

说实话,开源社区里面有很多人都在讲: 可达性算法中 JVM 会进行两次标记,第一次会标记所有对象,并找到继承实现了 finalize() 方法的对象,并查看该对象是否存在“自救”,这些内容都与《深入理解 Java 虚拟机》(后文简称为 ‘书’)中 3.2.4 生存还是死亡?这一小节存在出入,或者说几乎所有的博客都是通过阅读这一小节然后得到令人一知半解的回答,整个逻辑有点混乱,前后不搭,所有我打算总结一下 说明:虽然主要讲堆内存,但方法区也有 GC,只是条件更为苛刻(所有实例被回收、ClassLoader 被回收等)。 首先会先说明可达性分析算法的规则 其次会了解一下 finalize 方法,包括它的作用时机和作用次数 最后再来说一下 JVM 垃圾收集器根据 可达性分析算法 和 Java 对象机制怎么“两次标记”,怎么回收 Java

By Ne0inhk
《算法题讲解指南:优选算法-二分查找》--21.山峰数组的的峰顶索引,22.寻找峰值

《算法题讲解指南:优选算法-二分查找》--21.山峰数组的的峰顶索引,22.寻找峰值

🔥小叶-duck:个人主页 ❄️个人专栏:《Data-Structure-Learning》 《C++入门到进阶&自我学习过程记录》《算法题讲解指南》--从优选到贪心 ✨未择之路,不须回头 已择之路,纵是荆棘遍野,亦作花海遨游 目录 21. 山峰数组的的峰顶索引 题目链接: 题目描述: 题目示例: 解法(二分查找): 算法思路: C++算法代码: 算法总结及流程解析: 22. 寻找峰值 题目链接: 题目描述: 题目示例: 解法(二分查找): 算法思路: C++算法代码: 算法总结及流程解析: 结束语 21. 山峰数组的的峰顶索引 题目链接: 852. 山脉数组的峰顶索引 - 力扣(LeetCode) 题目描述: 题目示例: 解法(

By Ne0inhk

LeetCode 热题 100 Python3易懂题解(哈希,双指针,滑动窗口,子串)

链接可直接跳转 哈希 1. 两数之和(简单) 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。 你可以按任意顺序返回答案。 示例 1: 输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。 示例 2: 输入:nums = [3,2,4], target

By Ne0inhk