Floyd判圈算法(Floyd Cycle Detection Algorithm)

(/≧▽≦)/~┴┴ 嗨~我叫小奥 ✨✨✨

👀👀👀 个人博客:小奥的博客

👍👍👍:个人CSDN

⭐️⭐️⭐️:Github传送门

🍹 本人24应届生一枚,技术和水平有限,如果文章中有不正确的内容,欢迎多多指正!

📜 欢迎点赞收藏关注哟! ❤️

文章目录

一、基础概念

Floyd判圈算法(Floyd Cycle Detection Algorithm),又称龟兔赛跑算法(Tortoise and Hare Algorithm),是一种用于检测有限状态机、迭代函数或链表结构中是否存在环路的算法。该算法不仅能判断环的存在性,还可确定环的起点位置及其长度。

算法采用双指针策略,通过不同移动速度的指针遍历数据结构,根据指针相遇情况判定环路特征。

  • 时间复杂度 O(n)
  • 空间复杂度 O(1)

初始化:

  • 快慢指针:fast = slow = head
  • 单列表节点定义:
python 复制代码
from typing import Optional

class Node:
    """单链表节点定义"""
    __slots__ = ("val", "next")
    def __init__(self, val: int, nxt: "Optional[Node]" = None):
        self.val = val
        self.next = nxt

二、检测是否有环

  1. 慢指针每次前进一步:slow = slow.next
  2. 快指针每次前进两步:fast = fast.next.next
  3. 快慢指针相遇(slow == fast),则链表中必含环;否则无环。

为什么有环快慢指针一定能相遇?

若存在环,快指针相对于慢指针速度为1步/轮,必然会在环内相遇。

python 复制代码
# -------------------------------------------------
# 1. 探测是否有环(返回相遇节点或 None)
# -------------------------------------------------
def detect_cycle(head: Optional[Node]) -> Optional[Node]:
    """Floyd 第一阶段:龟兔赛跑"""
    slow = fast = head
    while fast and fast.next:
        slow = slow.next          # 1 步
        fast = fast.next.next     # 2 步
        if slow is fast:          # 指针同一对象
            return slow           # 返回相遇点
    return None                   # 无环

三、查找环的入口

  1. 相遇后,让慢指针slow回到头结点,另一指针fast停在相遇点:slow=head
  2. 之后让慢指针slow继续走,并从头结点开始记录距离:slow=slow.next, head=head.next
  3. 两个结点再次相遇的节点为环的入口
python 复制代码
# -------------------------------------------------
# 2. 定位环入口(若无环返回 None)
# -------------------------------------------------
def find_cycle_entry(head: Optional[Node]) -> Optional[Node]:
    meet = detect_cycle(head)
    if meet is None:
        return None
    # 第二阶段:同步一步一步走
    slow = head
    while slow is not meet:
        slow = slow.next
        meet = meet.next
    return slow      # 或 meet,二者同一节点

四、求环的长度

方法 1:单指针绕环一周(最常用)

  1. 任选环内一个节点,记为 p(可用入口节点,也可用第一次相遇点)。
  2. 令 q = p.next,计数器 cnt = 1。
  3. 当 q ≠ p 时循环
    q = q.next;cnt++。
  4. 返回 cnt。
    结论 :cnt 就是环长度 L。
    时间 O(L),空间 O(1)。
    ------ 这就是最简洁的"公式"L = 单次遍历回到起点的步数

方法 2:双指针再跑一次"龟兔"------一次就同时求出 L 与验证

(如果忘记保存入口节点,或者想再练一次快慢指针,可以用这个变种)

  1. 在第一次相遇点后,保持慢指针不动,把快指针重新指向相遇点。
  2. 快指针每次走 1 步,计数器 cnt = 0。
  3. 循环直到两指针再次相遇:
    fast = fast.next;cnt++。
  4. 返回 cnt。
    结论 :cnt 就是 L。
    原理:相对速度为 0,快指针恰好多跑一整圈。
python 复制代码
# -------------------------------------------------
# 3. 计算环长度(若无环返回 0)
# -------------------------------------------------
def cycle_length(head: Optional[Node]) -> int:
    meet = detect_cycle(head)
    if meet is None:
        return 0

    # 方法 1:单指针绕环一周
    # cur, cnt = meet.next, 1
    # while cur is not meet:
    #     cur = cur.next
    #     cnt += 1
    # return cnt

    # 方法 2:把 fast 重新指向 meet,两者都一次一步
    slow = meet
    fast = meet.next        # 相对距离 1
    cnt = 1                 # 已经隔开 1 步
    while slow is not fast:
        fast = fast.next    # 每次一步
        cnt += 1
    return cnt
相关推荐
江畔柳前堤1 天前
大语言模型分布式训练:从并行策略到万卡工程的系统梳理
人工智能·分布式·深度学习·算法·目标检测·机器学习·语言模型
Forever Nore1 天前
LeetCode 4 寻找两个正序数组的中位数 - 二分
算法·leetcode
罗西的思考1 天前
【OpenClaw具身硬件】MiniClaw 阅读笔记---(1)基础
人工智能·算法·机器学习
蛋先生DX1 天前
大模型参数存储格式揭秘:BF不是男朋友
深度学习·算法·llm
爱跳舞的烤冷面1 天前
自学嵌入式第22天(数据结构——哈希)
数据结构·算法·哈希算法
猎嘤一号1 天前
博弈论(Game Theory)的理论、算法与工程
人工智能·算法·安全·博弈论
月光船幽幽1 天前
影子模式下保护 logits 不被修改
人工智能·python·算法
马拉AI1 天前
腾讯开源 Agent 记忆系统,AI“换对话就忘”的问题有了新解法(附安装使用教程)
人工智能·算法·开源·科研
地平线开发者1 天前
征程6工具链模型X86推理方式说明
算法
地平线开发者1 天前
【征程6】校准量化中HistogramObserver解析
算法