有环:快慢指针从头出发,慢指针每次走1步、快指针每次走2步,若相遇则有环;无环:快指针先达NULL。关键在环内相对速度恒为1,必相遇,且需严格判空fast与fast->next以防越界。

快慢指针怎么判断链表有没有环
核心就一句话:两个指针从头出发,慢的每次走1步,快的每次走2步。如果它们在某个节点相遇,说明有环;如果快指针先走到null(或nullptr),说明无环。
关键不是“能不能追上”,而是“必然相遇”——只要存在环,快指针进入环后,相对速度恒为1步/轮,就像操场跑步,快的迟早套圈慢的,不存在永远差半步的情况。
代码里必须严格检查:fast != null && fast->next != null,否则访问fast->next->next会崩溃。
为什么快指针要走2步,不能走3步或更多
走2步是效率与安全的平衡点:
- 走1步:快慢同速,永远不相遇,失效
- 走2步:相对速度稳定为1,数学上保证有限步内相遇,且边界判断简单(只需检查
fast和fast->next) - 走3步及以上:虽仍可能相遇,但需更复杂的越界检查(比如走3步要判
fast、fast->next、fast->next->next),增加出错风险,收益却没提升
常见误操作和边界情况
实际写代码时,这几个细节最容易翻车:
- 起始位置必须相同:slow和fast都从head开始,不能一个从head、一个从head->next
- 空链表或单节点链表要兼容:此时fast->next直接为null,while循环不执行,直接返回无环,逻辑自然成立
-
相遇判断必须放在移动之后:先更新指针,再比较
slow == fast;若提前判断,初始时两者相等会误报“有环” - 不要用计数器限制循环次数:有人担心死循环加count > N就退出——这反而掩盖真实问题,且N难设定;正确做法是依赖指针是否到达null
它不只是用来判环
快慢指针的“速度差+环中追及”模型,延伸出多个高频应用:
- 找链表中点:快指针到尾,慢指针刚好到中点(奇数长度取正中,偶数取后中)
- 找环入口点:相遇后,把一个指针拉回head,两指针都改走1步,再次相遇处就是环入口
- 判断链表是否回文:先找中点、后半段反转,再双指针逐对比较
这些都不是黑魔法,本质都是对“相对运动节奏”的精准控制。

















