1. 环形链表检测与入口定位解析
今天我想分享一个在链表操作中非常经典的问题——如何检测链表中的环并找到环的起始节点。这个问题在技术面试中出现的频率相当高,我在准备面试时也曾经被它难倒过几次。经过反复练习和思考,现在终于能够游刃有余地解决它了。
1.1 问题定义与核心挑战
给定一个单链表的头节点head,我们需要完成两个任务:
- 判断链表中是否存在环
- 如果存在环,找到环的入口节点
这个问题看似简单,但要在O(1)空间复杂度内解决并不容易。我第一次遇到这个问题时,第一反应是用哈希表记录访问过的节点,但这样空间复杂度就是O(n)了,不符合进阶要求。
1.2 快慢指针法的直观理解
快慢指针法(Floyd判圈算法)是这个问题的经典解决方案。它的核心思想是:
- 让两个指针以不同速度遍历链表
- 快指针每次移动两步,慢指针每次移动一步
- 如果链表无环,快指针会先到达终点
- 如果链表有环,快慢指针最终会在环内相遇
这个方法的精妙之处在于,当快慢指针相遇后,我们还能利用这个相遇点来找到环的入口。具体原理我会在后面详细解释。
2. 算法原理深度剖析
2.1 数学证明:为什么快慢指针会相遇
假设链表无环部分长度为L,环的长度为C。当慢指针进入环时,快指针已经在环内,设此时快指针距离慢指针的距离为d(0 ≤ d < C)。
由于快指针每次比慢指针多走一步,它们之间的距离每次减少1,因此最多经过C-d次移动后,快指针就会追上慢指针。
2.2 环入口定位的数学依据
当快慢指针相遇后,我们可以证明:从链表头到环入口的距离,等于从相遇点到环入口的距离。这就是为什么我们可以在快慢指针相遇后,再让一个指针从链表头出发,与慢指针同步移动,它们相遇的点就是环的入口。
证明过程:
设链表头到环入口距离为L,环入口到相遇点距离为x,相遇点到环入口距离为y(即C = x + y)
当快慢指针相遇时:
- 慢指针走了L + x步
- 快指针走了L + x + nC步(n为快指针在环内绕的圈数)
因为快指针速度是慢指针的两倍:
2(L + x) = L + x + nC
=> L = nC - x = (n-1)C + y
这意味着从链表头走L步,和从相遇点走(n-1)C + y步,会到达同一个点——环的入口。
