【忍者算法】从入环点到相遇点:深入理解环形链表 II|LeetCode第142题

问题升级:不止要找环,还要找入环点

在上一题中,我们讨论了如何判断链表是否有环。现在让我们更进一步:如果确定链表中有环,我们该如何找到环的入口节点?这就像是在环形跑道上不仅要确认跑道是环形的,还要找到环形跑道的起点。

问题描述

LeetCode第142题"环形链表 II"要求:给定一个链表的头节点 head,返回链表开始入环的第一个节点。如果链表无环,则返回 null。

例如:

输入:3 → 2 → 0 → -4
↑___________|
输出:返回节点 2
解释:链表中存在一个环,其尾部连接到第二个节点

从快慢指针相遇谈起

还记得上一题中的快慢指针相遇吗?那个相遇点看似随机,实际上蕴含着重要的数学原理。让我们用这个相遇点来找到入环点。

巧妙的数学关系

假设:

  • 链表头到入环点的距离为 a
  • 入环点到相遇点的距离为 b
  • 相遇点到入环点的距离为 c

当快慢指针相遇时:

  1. 慢指针走过的距离:a + b
  2. 快指针走过的距离:a + b + n(b + c),其中n是快指针在环内走的圈数
  3. 因为快指针速度是慢指针的两倍,所以:2(a + b) = a + b + n(b + c)

通过解这个等式,我们发现:a = c + (n-1)(b + c)

这意味着:从链表头和相遇点同时出发,最终会在入环点相遇!

代码实现

public ListNode detectCycle(ListNode head) {
// 处理特殊情况
if (head == null || head.next == null) {
return null;
} // 第一阶段:使用快慢指针找到相遇点
ListNode slow = head;
ListNode fast = head;
ListNode intersection = null; while (fast != null && fast.next != null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
intersection = slow;
break;
}
} // 如果没有相遇点,说明无环
if (intersection == null) {
return null;
} // 第二阶段:从头节点和相遇点同时出发,找入环点
ListNode start = head;
while (start != intersection) {
start = start.next;
intersection = intersection.next;
} return start;
}

图解过程

1) 初始状态:
3 → 2 → 0 → 4
↑___________|
S,F 2) 快慢指针相遇:
3 → 2 → 0 → 4
↑___________|
S,F 3) 从头和相遇点同时出发:
3 → 2 → 0 → 4
↑___________|
P1 P2 4) 在入环点相遇:
3 → 2 → 0 → 4
↑___________|
P1,P2

与上一题的联系与进阶

相比环形链表I,这一题是一个很自然的进阶:

  1. 两题都使用了快慢指针技巧
  2. 这一题复用了上一题找相遇点的过程
  3. 在找到相遇点后,增加了寻找入环点的步骤

实现细节与优化

  1. 空间复杂度仍然保持O(1)
  2. 时间复杂度为O(n)
  3. 不需要额外的数据结构
  4. 代码实现优雅且直观

思考与延伸

这个问题告诉我们:

  1. 有时问题的解决方案就藏在问题本身的特性中
  2. 数学关系可以帮助我们找到优雅的解法
  3. 快慢指针不仅能检测环,还能帮我们找到关键节点

实际应用思考

这个算法的思想可以应用在很多实际场景中:

  1. 检测循环依赖
  2. 死锁检测
  3. 循环引用的处理

让我们记住:当我们遇到类似的"寻找特殊点"问题时,可以尝试利用路径特性来找到优雅的解决方案。


作者:忍者算法

公众号:忍者算法

我准备了一份刷题清单,以及这些题目的详细题解,覆盖了绝大部分常见面试题。我可以很负责任地说,只要你把这些题真正掌握了,80%的算法面试都能遇到相似题目。公众号回复【刷题清单】获取~

【忍者算法】从入环点到相遇点:深入理解环形链表 II|LeetCode第142题 环形链表 II的更多相关文章

  1. 龟兔赛跑算法 floyed判环算法

    今天写线段树写到要用到这个算法的题目,简单的学习一下. https://blog.csdn.net/javaisnotgood/article/details/89243876 https://blo ...

  2. (zhuan) 大牛讲堂 | 算法工程师入门第二期-穆黎森讲增强学习

    大牛讲堂 | 算法工程师入门第二期-穆黎森讲增强学习 2017-07-13 HorizonRobotics

  3. 3,java数据结构和算法:约瑟夫环出队顺序, 单向环形链表的应用

    什么是约瑟夫环? 就是数小孩游戏: 直接上代码: 要实现这个,只需要理清思路就好了 孩子节点: class Boy{ int no;//当前孩子的编码 Boy next; // 下一节点 public ...

  4. 【算法分析】如何理解快慢指针?判断linked list中是否有环、找到环的起始节点位置。以Leetcode 141. Linked List Cycle, 142. Linked List Cycle II 为例Python实现

    引入 快慢指针经常用于链表(linked list)中环(Cycle)相关的问题.LeetCode中对应题目分别是: 141. Linked List Cycle 判断linked list中是否有环 ...

  5. [LeetCode] 142. Linked List Cycle II 单链表中的环之二

    Given a linked list, return the node where the cycle begins. If there is no cycle, return null. To r ...

  6. 【算法训练营day4】LeetCode24. 两两交换链表中的结点 LeetCode19. 删除链表的倒数第N个结点 LeetCode面试题 02.07. 链表相交 LeetCode142. 环形链表II

    [算法训练营day4]LeetCode24. 两两交换链表中的结点 LeetCode19. 删除链表的倒数第N个结点 LeetCode面试题 02.07. 链表相交 LeetCode142. 环形链表 ...

  7. LeetCode 上最难的链表算法题,没有之一!

    题目来源于 LeetCode 第 23 号问题:合并 K 个排序链表. 该题在 LeetCode 官网上有关于链表的问题中标注为最难的一道题目:难度为 Hard ,通过率在链表 Hard 级别目前最低 ...

  8. [LeetCode] 141. Linked List Cycle 链表中的环

    Given a linked list, determine if it has a cycle in it. Follow up:Can you solve it without using ext ...

  9. [LeetCode] 142. Linked List Cycle II 链表中的环 II

    Given a linked list, return the node where the cycle begins. If there is no cycle, return null. Foll ...

  10. LeetCode初级算法--链表02:合并两个有序链表

    LeetCode初级算法--链表02:合并两个有序链表 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn. ...

随机推荐

  1. Vue.js vuex

    1.前言 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,它解决了vue中不同组件之间状态共享的问题. 通俗的说,它就是一个带响应式的全局变量管理,它数据的改变会触发相关页面/组件的更 ...

  2. Spring AOP基础、快速入门

    介绍 AOP,面向切面编程,作为面向对象的一种补充,将公共逻辑(事务管理.日志.缓存.权限控制.限流等)封装成切面,跟业务代码进行分离,可以减少系统的重复代码和降低模块之间的耦合度.切面就是那些与业务 ...

  3. 搭建一个文件存储服务器minio,实现文件存储

    搭建一个文件存储服务器minio,实现文件存储 Minio是一个开源的.自托管的对象存储服务器,它提供了类似于云存储服务的功能.你可以使用Minio搭建自己的私有云存储解决方案,或者作为公共存储服务的 ...

  4. .NET Core 堆结构(Heap)底层原理浅谈

    .Net托管堆布局 加载堆 主要是供CLR内部使用,作为承载程序的元数据. HighFrequencyHeap 存放CLR高频使用的内部数据,比如MethodTable,MethodDesc. 通过i ...

  5. Dapr-6: Dapr 状态管理构建块

    第 6 章 Dapr 状态管理构建块 The Dapr state management building block | Microsoft Docs 分布式应用程序由一组独立的服务构成.尽管每个服 ...

  6. 【爬虫】XPath实例

    题目要求我们用XPATH去爬某个网站并且保存为CSV文件 代码如下,仅供参考 # -*- coding: UTF-8 -*- # 开发人员:萌狼蓝天 # 博客:Https://mllt.cc # 笔记 ...

  7. docker.sock: connect: permission denied 解决

    问题描述xjun@DESKTOP-L2R4GKN:~$ docker run -it hello-worlddocker: Got permission denied while trying to ...

  8. Xshell无法连接22端口问题解决办法汇总

    Xshell软件在进行远程连接过程中,会出现端口连接报错的问题,提示:"该IP地址的22端口连接失败",这是怎么回事?今天小编就xshell软件无法连接22端口的问题,整理相关情形 ...

  9. com.sun.xml.internal.messaging.saaj.util 不存在

    maven 编译时报错:程序包com.sun.xml.internal.messaging.saaj.util不存在需要添加 <compilerArguments> <verbose ...

  10. Qt/C++编写地图应用/离线地图下载/路径规划/轨迹回放/海量点/坐标转换

    一.前言说明 这个地图组件写了很多年了,最初设计的比较粗糙,最开始只是为了满足项目需要,并没有考虑太多拓展性,比如最初都是按照百度地图写死在代码中,经过这几年大量的现场实际应用,以及大量的用户提出的改 ...