怒江傈僳族自治州网站建设_网站建设公司_支付系统_seo优化
2025/12/18 17:08:24 网站建设 项目流程

—— 基于快慢指针(Floyd 判圈算法)

一、问题背景

在单链表中,某些节点的 next 指针可能会指向链表中已经出现过的节点,从而形成 环形结构
常见问题包括:

  1. 判断链表是否存在环
  2. 如果存在环,找到 环的入口节点

二、链表节点定义

class ListNode
{public int value;public ListNode next;
}
  • value:节点存储的数据
  • next:指向下一个节点的引用

三、核心思想:快慢指针(Floyd 判圈算法)

指针定义

  • 慢指针(slowPointer)
    • 每次向前移动 1 步
  • 快指针(fastPointer)
    • 每次向前移动 2 步
slow: 1 step / loop
fast: 2 steps / loop

四、判环原理说明

1. 无环情况

  • 快指针会率先走到链表末尾
  • 出现 fast == nullfast.next == null
  • 直接判定:无环

2. 有环情况

  • 快指针与慢指针都会进入环中
  • 快指针速度更快
  • 在环中必然会 追上慢指针
  • 一旦出现:
slowPointer == fastPointer

即可确认链表存在环


五、判环代码实现

static bool HasCycle(ListNode node)
{if (node == null || node.next == null){return false;}ListNode slowPointer = node;ListNode fastPointer = node;while (fastPointer != null && fastPointer.next != null){slowPointer = slowPointer.next;fastPointer = fastPointer.next.next;if (slowPointer == fastPointer){// 发现环return true;}}return false;
}

六、为什么快慢指针一定能相遇?

设:

  • 从链表头到环入口的长度为 a
  • 环的长度为 b
    当慢指针进入环时:
  • 快指针已经在环中领先若干步
  • 两者在环中相对速度为 1
  • 相对位移在 b 的模意义下递增
    因此:

必然在有限步内相遇


七、寻找环入口的数学原理

当快慢指针第一次相遇时:

  • 快指针重新指向链表头
  • 慢指针保持在相遇点
  • 两个指针 每次都走 1 步
  • 再次相遇的节点,就是 环入口

八、查找环入口的代码实现

if (slowPointer == fastPointer)
{fastPointer = node; // 重置快指针到链表头while (slowPointer != fastPointer){slowPointer = slowPointer.next;fastPointer = fastPointer.next;}Console.WriteLine($"环入口是值为 {slowPointer.value} 的节点");return true;
}

九、完整算法流程总结

1. 初始化 slow 和 fast 指针指向头节点
2. slow 每次走 1 步,fast 每次走 2 步
3. 若 fast 走到 null,说明无环
4. 若 slow == fast,说明有环
5. fast 重置到头节点
6. slow 与 fast 同速前进
7. 再次相遇点即为环入口

十、时间与空间复杂度分析

时间复杂度

  • 判环:O(n)
  • 找入口:O(n)
    总时间复杂度:O(n)

空间复杂度

  • 只使用常数个指针
    空间复杂度:O(1)

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询