环形链表的数学之美:用龟兔赛跑破解悬案

142 阅读2分钟

某天深夜,程序员小明接到报警:链表王国发生一起离奇失踪案。一个链表节点在巡逻时突然消失,监控显示它在链表迷宫中反复绕圈。作为算法侦探,我们需要找到这个迷宫的入口,解救被困节点。

一、案发现场勘查

我们首先观察这个特殊链表的结构(如图示):

  1. 直线区段长度为 L(从头节点到环入口)
  2. 环形周长为 C(环内节点数量)
  3. 相遇点距入口 S 步(快慢指针相遇位置)

image.png

二、经典双指针破案法

2.1 第一轮追击:确认环形存在

let slow = head, fast = head;
while (fast && fast.next) {
    slow = slow.next;      // 乌龟速度1
    fast = fast.next.next; // 兔子速度2
    
    if (slow === fast) {   // 相遇点确认
        // 进入第二轮定位
    }
}

数学推导

  • 当兔子追上乌龟时,兔子跑过的距离是乌龟的2倍
  • 设相遇时乌龟走了 K 步,则:
    L + S = K
    L + nC + S = 2K
    解得:L = nC - S → L = (C - S) + (n-1)C

2.2 第二轮定位:寻找环形入口

let ptr = head;
while (ptr !== slow) {
    ptr = ptr.next;   // 新指针从起点出发
    slow = slow.next;  // 乌龟继续前进
}
return ptr; // 相遇点即为入口

关键证明
根据第一轮推导结果,新指针走过 L 步到达入口时:

  • 乌龟从相遇点出发走过 (C - S) 步
  • 此时两者在入口处相遇:L = (C - S) + (n-1)C

三、复杂度分析

指标数值说明
时间复杂度O(N)线性遍历两次链表
空间复杂度O(1)仅使用固定数量指针
准确率100%数学保证必然找到入口

四、案件还原实战演练

案例1:标准环形链表\

屏幕截图 2025-05-06 104829.png 输入:1 → 2 → 3 → 4(4指向2)
推导:

  • 第一轮相遇时:slow=2,fast=2
  • 第二轮定位:ptr从1出发,slow从2出发
  • 相遇点2即为入口

案例2:全环形链表\

image.png 输入:A → B → C → A
推导:

  • 第一轮相遇点:B(A→B→C→A→B)
  • 第二轮定位:ptr从A出发,slow从B出发
  • 经过2步同时到达A点

五、高阶应用场景

  1. 内存泄漏检测:追踪对象引用环
  2. 无限循环识别:判断递归调用链
  3. 环形缓冲区优化:高效存储数据流

六、侦探笔记总结

  • 核心思想:将环形问题转化为追击问题
  • 关键公式:L = (C - S) + (n-1)C
  • 代码要点:双指针速度差为2保证必然相遇
  • 思维延伸:该算法思想可应用于各类循环检测

若将快指针速度改为3步/次,算法是否仍然有效?