力扣刷题TOP101:6.BM7 链表中环的入口结点

目录:

目的

思路

复杂度

记忆秘诀

python代码

目的

{1,2},{3,4,5}, 3 是环入口。


思路

这个任务是找到带环链表的环入口。可以看作是上一题龟兔赛跑(Floyd 判圈算法)的延续版:乌龟愤愤不平地举报兔子跑得太快,偷偷回头朝自己炫耀得瑟,还说在环口撒了尿标记。裁判接到举报,准备调取“监控记录”,验证兔子是否偷偷回头,并定位撒标记的位置(环入口)。


裁判开始审理过程

  • 参赛选手:

    • 乌龟(慢指针slow): 每次只走一步,慢悠悠的。slow = head
    • 兔子(快指针fast): 从同样的起点出发,每次跳两步,永远快人一步。fast = head
    • 观察双方起点位置,从同样的起点出发

比赛规则:

只要兔子还没跑出链表(fast != Nonefast.next != None),比赛继续。

  • 为什么检查两个条件?
    • fast 如果 fast == None,说明兔子已经跑到了链表的尽头,没有环。
    • fast.next 是兔子跳两步时需要访问的下一个节点。fast.next == None,说明兔子已经没有“下一步”可以跳,也意味着链表没有环。

比赛开始:

  • 乌龟稳步前进 走一步,代表慢速slow = slow.next。
  • 兔子飞速跳跃 跳两步,代表快速移动fast = fast.next.next。
  • 是否龟兔同镜相遇点 如果他们在一个镜头中出现(slow == fast),裁判记录兔子回头了,继续调查。如果没有出现(环),直接结束,乌龟举报无效,返回 None
  • 为什么一定会相遇?
    • 如果链表是闭环,兔子因为步伐更快,最终会在环内兜圈,追上乌龟。

寻找兔子撒尿点(环口):

  • 裁判让乌龟回到起点:

    • 乌龟回到起点,准备和兔子一同慢跑:slow = pHead
  • 兔子在相遇点陪乌龟慢慢走:

    • 这次双方步伐一致,每次只走一步:
      • slow = slow.next
      • fast = fast.next
  • 两者最终相遇(具体可查看下面详细的数学推导

    • 当两者再次相遇时slow == fast,位置就是环的入口节点,也就是兔子撒尿炫耀的地方。

举报成功:

  • 裁判员找到了兔子撒尿标记的地方(环的入口节点)并提交结果return slow,乌龟举报成功,取消兔子的比赛成绩。

复杂度

  • 时间复杂度:O(n)

    • 每次兔子和乌龟各走一段路,总路程不会超过链表长度的两倍。
  • 空间复杂度:O(1)

    • 只用了两只小动物(两个指针变量),省吃俭用,不多花内存。

记忆秘诀

  1. 乌龟走一步,兔子跳两步。
  2. 链表有环,相遇无误。
  3. 链表无环,兔子先停步。
  4. 环点未锁住,乌龟再起步
  5. 兔子陪跑步,入口终汇聚

补充:数学推导

设链表为一个带环的结构,其中:

  • a:链表头节点到环入口的距离(环前的直线段)。
  • b:环入口到相遇点的距离(在环中的第一部分)。
  • c:相遇点到环入口的剩余距离(环中的第二部分)。
  • n:兔子绕环的圈数。
  • 兔子的距离是乌龟的两倍:

                                                2(a+b)=a+b+n(b+c)
    • 兔子每次跳两步,乌龟每次走一步,因此兔子走的距离总是乌龟的两倍。
  • 化简公式:消去公共项 a+b,得到:a=c+(n−1)(b+c)

    • 乌龟的距离:当乌龟从起点走 a距离时,会刚好到达环的入口。

    • 兔子的距离:兔子从相遇点出发,绕过 c距离后也会到达环的入口。

    • 同步抵达环入口:因为 n−1表示兔子可能多绕了若干圈,但最终兔子和乌龟都会同时抵达环入口。

  • 找到环入口的核心原因:

    • 相遇后,将乌龟放回起点,兔子留在相遇点。
    • 两者按相同速度行进(每次一步),兔子绕过剩余的 c 距离时,乌龟正好走完 a,两者在环入口相遇。

python代码

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
     def EntryNodeOfLoop(self, pHead: ListNode) -> ListNode:
        # 快慢指针法:检测环
        slow = pHead
        fast = pHead

        # 检测是否有环
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            if slow == fast:  # 快慢指针相遇,说明有环
                break
        else:
            return None  # 如果没有环,返回 None

        # 重新开始寻找环的入口
        slow = pHead  # 慢指针重新指向头节点
        while slow != fast:
            slow = slow.next
            fast = fast.next  # 两个指针每次都走一步

        # 相遇时即为环的入口
        return slow

* 欢迎大家探讨新思路,能够更好的理解和记忆

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网关: 用途和产品对比

概述 微服务中的有一个非常关键的组件: API网关 和配置中心一样,在没有采用微服务架构的时候 我们可以自己搭建自己的API网作作为统一的 API 出口和安全验证 在微服务架构之下,服务被拆的非常的零散,在降低了耦合度的同时 也给服务的统一…

Java ConcurrentHashMap

Java Map本质不是线程安全的,HashTable和Collections同步包装器(Synchronized Wrapper)在并发场景下性能低。Java还为实现 Map 的线程安全提供了并发包,保证线程安全的方式从synchronize简单方式到精细化,比如Concurre…

Spring 自调用事务失效分析及解决办法

前言 博主在写公司需求的时候,有一个操作涉及到多次对数据库数据的修改。当时就想着要加 Transactional注解来声名事务。并且由于一个方法中有太多行了,于是就想着修改数据库的操作单独提取出来抽象成一个方法。但这个时候,IDEA 提示我自调用…

【LeetCode每日一题】——189.轮转数组

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【题目进阶】八【解题思路】九【时空频度】十【代码实现】十一【提交结果】 一【题目类别】 数组 二【题目难度】 中等 三【题目编号】 189.轮转数组 四【题目描述】 …

Spark基本命令详解

文章目录 Spark基本命令详解一、引言二、Spark Core 基本命令1、Transformations(转换操作)1.1、groupBy(func)1.2、filter(func) 2、Actions(动作操作)2.1、distinct([numTasks])2.2、sortBy(func, [ascending], [numTasks]) 三、…

AppFlow:支持飞书机器人调用百炼应用

AppFlow:支持飞书机器人调用百炼应用 简介: 本文介绍了如何创建并配置飞书应用及机器人,包括登录飞书开发者后台创建应用、添加应用能力和API权限,以及通过AppFlow连接流集成阿里云百炼服务,最后详细说明了如何将机器…

基于vite创建一个脚手架(快速入门)

Vite是一种新型的前端构建工具,主要用于构建现代化的Web应用程序。以 原生ESM 方式提供源码。这实际上是让浏览器接管了打包程序的部分工作:Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际…

学习ASP.NET Core的身份认证(基于Session的身份认证1)

ASP.NET Core使用Session也可以实现身份认证,关于Session的介绍请见参考文献5。基于Session的身份认证大致原理就是用户验证成功后将用户信息保存到Session中,然后在其它控制器中从Session中获取用户信息,用户退出时清空Session数据。百度基于…

视觉语言模型(VLM)学习笔记

目录 应用场景举例 VLM 的总体架构包括: 深度解析:图像编码器的实现 图像编码器:视觉 Transformer 注意力机制 视觉-语言投影器 综合实现 训练及注意事项 总结 应用场景举例 基于文本的图像生成或编辑:你输入 “生成一张…

spider--某站搜索--自动化dp

免责声明:本文仅作分享! 自动化: DrissionPage DrissionPage官网 import time from DrissionPage import ChromiumPage,ChromiumOptions import pandas as pd# 这里配置了浏览器路径,不配置的话直接 page ChromiumPage() co Ch…

学成在线day07

视频处理 技术方案 掌握了xxl-job的分片广播调度方式,下边思考如何分布式去执行学成在线平台中的视频处理任务。 任务添加成功后,对于要处理的任务会添加到待处理任务表中,现在启动多个执行器实例去查询这些待处理任务,此时如何…

vsftpd 的安装和应用(超详细!!!)

FTP(File Transfer Protocol,文件传输协议)是一种用于在计算机网络上进行文件传输的标准协议。它允许用户从一台计算机向另一台计算机上传或下载文件。FTP的工作原理涉及到客户端和服务器之间的交互,以及数据传输的过程。 一、FT…

学习笔记:黑马程序员JavaWeb开发教程(2024.11.29)

10.5 案例-部门管理-新增 如何接收来自前端的数据: 接收到json数据之后,利用RequestBody注解,将前端响应回来的json格式的数据封装到实体类中 对代码中Controller层的优化 发现路径中都有/depts,可以将每个方法对应请求路径中的…

基于Java的小程序电商商城开源设计源码

近年来电商模式的发展越来越成熟,基于 Java 开发的小程序电商商城开源源码,为众多开发者和企业提供了构建个性化电商平台的有力工具。 基于Java的电子商城购物平台小程序的设计在手机上运行,可以实现管理员;首页、个人中心、用户…

JiaJia-CP-1,2,3的WP(1)

一.JiaJia-CP-1 这是ctfshow里电子取证里面的题,以下下是我做题时的WP 审题,最后提交格式要进行md5 加密,给各位CTFer们找了一个md5加密的网站(加紧收藏哦): MD5 在线加密工具 | 菜鸟工具 1.拿到题目&am…

微信小程序下拉刷新与上拉触底的全面教程

微信小程序下拉刷新与上拉触底的全面教程 引言 在微信小程序的开发中,用户体验至关重要。下拉刷新和上拉触底是提高用户交互体验的重要功能,能够让用户轻松获取最新数据和内容。本文将详细介绍这两个功能的实现方式,结合实际案例、代码示例和图片展示,帮助开发者轻松掌握…

Vision Transformer(vit)的主干

图解: 代码: class VisionTransformer(nn.Module):def __init__(self, img_size224, patch_size16, in_c3, num_classes1000,embed_dim768, depth12, num_heads12, mlp_ratio4.0, qkv_biasTrue,qk_scaleNone, representation_sizeNone, distilledFalse,…

无人机的起降装置:探索起飞和降落的秘密 !

一、起降系统的运行方式 起飞方式 垂直起飞:小型无人机通常采用垂直起飞方式,利用螺旋桨产生的升力直接从地面升起。这种方式适用于空间有限或需要快速起飞的场景。 跑道起飞:大型无人机或需要较长起飞距离的无人机,可能会采用…

【VUE3】npm : 无法加载文件 D:\Program\nodejs\node_global\npm.ps1,因为在此系统上禁止运行脚本。

npm : 无法加载文件 D:\Program\nodejs\npm.ps1。未对文件 D:\Program\nodejs\npm.ps1 进行数字签名。无法在当前系统上运行该脚本。有关运行脚本和设置执行策略的详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID135170 中的 about_ Execution_Policies。…

跨平台应用开发框架(4)----Qt(系统篇)

目录 1.Qt事件 1.事件来源 2.事件处理 3.按键事件 1.组合按键 4.鼠标事件 1.鼠标单击事件 2.鼠标释放事件 3.鼠标双击事件 4.鼠标移动事件 5.滚轮事件 5.定时器 1.QTimerEvent类 2.QTimer 类 3.获取系统日期及时间 6.事件分发器 7.事件过滤器 2.Qt文件 1.输入…