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

Floyd判圈和Brent判圈

问题背景

想象一个链表,它可能在某个节点处指向一个之前的节点,从而形成一个环。

我们的目标是:

  • 判断链表中是否存在环。

  • 找到环的入口点。

  • 计算环的长度。

比如说这个:

1 -> 2 -> 3 -> 4 -> 5 -> 6^         ||         v9 <- 8 <- 7

节点 \(4\) 即为环的入口点,环的长度为 \(6\)

Floyd 判圈算法 (龟兔赛跑算法)

使用两个指针,一个慢指针(乌龟)和一个快指针(兔子)。

慢指针:每次移动一步。

快指针:每次移动两步。

判断是否有环的原理:如果链表中存在环,那么快指针最终会追上慢指针(在环内相遇)。如果不存在环,快指针会先到达链表尾部。

算法步骤如下:

  • 初始化:

    • 指针 \(slow\)\(fast\) 都指向链表头节点。
  • 移动阶段:

    • 在每一步中,\(slow\) 向后移动一个节点。
    • \(fast\) 向后移动两个节点。
    • 检查 \(fast\)\(fast.next\) 是否为 \(null\)。如果是,则链表无环,算法结束。
    • 检查 \(slow\) == \(fast\)。如果相等,则链表有环。
  • 寻找环入口:

    • \(slow\)\(fast\) 第一次相遇时,将其中一个指针重新指向链表头。
    • 然后,两个指针都以每次一步的速度移动。
    • 当它们再次相遇时,相遇的节点就是环的入口点。

那问题来了,为什么重新指向头节点后,再次相遇的点就是环入口?

我们设链表头到环入口的距离为 \(A\),环入口到第一次相遇点的距离为 \(B\),第一次相遇点回到环入口的距离为 \(C\)

那么环的长度 \(L = B + C\)

在第一次相遇时:

慢指针走过的路程:\(A + B\)

快指针走过的路程:\(A + B + k * L\)(其中 \(k\) 是快指针在环内转的圈数)。

由于快指针速度是慢指针的两倍,所以路程也是两倍,所以 \(2(A + B) = A + B + k * L\)\(A = k * L - B\)

\(L = B + C\) 代入:\(A = k * (B + C) - B\)\(A = (k-1) * L + C\)

从链表头(\(A\))到环入口的距离,等于从第一次相遇点(\(C\))绕 \((k-1)\) 圈再回到环入口的距离。

所以,一个指针从链表头走 \(A\) 步,另一个指针从相遇点走 \(C + (k-1)*L\) 步,它们最终会在环入口点相遇。

Brent 判圈算法

通常比 Floyd 有更低的时间常数,但好像没啥人学啊。

使用一个慢指针和一个快指针,但快指针不是连续移动,而是“跳跃式”移动。

慢指针:保持不动,直到快指针需要“跳跃”到它的位置。

快指针:每次移动一步,但每走一段距离(\(step_limit\)),如果还没遇到慢指针,就将 \(step_limit\) 翻倍,并把慢指针移动到快指针的当前位置。

算法步骤如下:

  • 初始化:
    • \(slow\) = \(head\), \(fast\) = \(head\)
    • \(step_limit = 2\) (初始的移动限制)
    • \(steps_taken = 0\) (记录当前周期内已走的步数)
  • 移动阶段:
    • \(fast = fast.next\) (快指针走一步)
    • \(steps_taken += 1\)
    • 检查 \(fast == slow\)。如果相等,则发现环。
    • 检查 \(steps_taken == step_limit\)
    • 如果相等,说明当前周期走完了。将 \(slow\) 移动到 \(fast\) 的位置(让乌龟跳到兔子当前位置)。将 \(step_limit *= 2\),并将 \(steps_taken\) 重置为 \(0\)

寻找环入口和长度:

一旦检测到环(\(fast\) == \(slow\)),环的长度就是此时 \(steps_taken\) 的值(因为 \(slow\) 没动过,\(fast\) 走了 \(steps_taken\) 步追上它)。

要找到环入口,可以将两个指针都重置为头节点,然后让一个指针先走环长度步,然后两个指针同时一步一步走,相遇点就是入口啦。

http://www.jsqmd.com/news/42304/

相关文章:

  • obet(Oracle Block Editor Tool)第二版发布
  • 2025年石棉橡胶板厂家联系方式汇总:服务覆盖与区域分布
  • WebStorm 2025.2.4, 11月最新版 安装、授权、使用说明
  • 2025 最新推荐!汽车喇叭网生产厂家权威排行榜 0.01MM 精度 + 全工艺保障靠谱品牌甄选
  • 2025年石棉橡胶板厂家联系方式汇总:专业服务与产品解析
  • C# Avalonia 18- ControlTemplates - ColorPickerTwoWays
  • 【GitHub每日速递 20251117】一款感知屏幕万物的交互式AI助手,Everywhere带你体验无缝支持! #
  • 智表ZCELL产品V3.4 版发布,新增区域筛选、字母列参等功能。
  • 享元模式实验围棋软件
  • 元推理品析:自指有机,自洽有缘
  • C#/.NET/.NET Core技术前沿周刊 | 第 61 期(2025年11.10-11.16)
  • The 4th Universal Cup. Stage 5: Grand Prix of Nanjing 做题笔记
  • Java开发中最那些常见的坑,你踩过几个?
  • 量化网络风险:持续DDoS测试的运营投资回报
  • qqw
  • Tenable Nessus 10.11 新增功能简介
  • 上述
  • 详细介绍:Vue3 表单输入绑定
  • Splunk Enterprise 10.0.2 发布 - 搜索、分析和可视化,数据全面洞察平台
  • midwayjs 自定义组件开发
  • Apache NetBeans 28 发布 - Java 等多语言开源跨平台 IDE
  • 读社会工程:安全体系中的人性漏洞(第2版)04读懂对方的暗示
  • 解密Prompt系列64. Anthropic Skils的延伸思考
  • [题解]【MX-S11】梦熊 NOIP 2025 模拟赛 3 WAOI R7 FeOI R6.5(同步赛) T1~T2
  • C# 常用控件(学习笔记6)
  • 移动应用安全测试全面指南:方法与最佳实践
  • Ai元人文:“退一万步”的设想
  • TikTok(抖音)国际现代风水指南1什么是风水?
  • AI元人文:人机差异律——《人机互觉协议》草案
  • Windows-icacls