目录:算法日记
原题链接:142. 环形链表 II - 力扣(LeetCode) (leetcode-cn.com)
题目描述
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改链表。
数据范围
- 链表中节点的数目范围在范围内
pos的值为或者链表中的一个有效索引- 使用
O(1)空间复杂度解决此题
题目示例
输入: head = [3,2,0,-4], pos = 1
输出: 返回索引为 1 的链表节点
解释: 链表中有一个环,其尾部连接到第二个节点。
算法思路
设置两个指针,蓝色为快指针,黄色为慢指针。快指针小蓝每次走两步,慢指针小黄每次走一步。若不存在环,则快指针小蓝一定可以走到null。若存在环,由于环上每个结点出边唯一,因此快指针小蓝一定可以和慢指针小黄在环上某点相遇,相遇点记为汇合点,进入环的入口记为入口。
设起点到入口的距离为,则当慢指针小黄走到入口处时,快指针小蓝已走了,记此时快指针小蓝所在位置为标记点,则入口到标记点的距离为。为了方便表述,设入口到汇合点的距离为,则慢指针小黄从入口处开始到汇合点走了步,快指针小蓝从标记点到汇合点走了步,因此,标记点到入口的距离也为。
综上所述,入口到标记点的距离为,标记点到入口的距离为,入口到会合点的距离也为,因此,汇合点到入口的距离即为。到这里就可以得出,从起点到入口的距离,与从汇合点到入口的距离是相等的。
根据上述证明,首先通过快慢指针找到汇合点,然后两个指针分别从起点与汇合点同速出发,相遇点即为入口。注意特判不存在环的情况。
AC代码
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var detectCycle = function(head) {
if(head == null || head.next == null) return null;
let slow = head;
let fast = head;
while(fast != null) {
slow = slow.next;
fast = fast.next;
if(fast == null) return null;
fast = fast.next;
if(slow == fast) { //找到汇合点
slow = head;
while(slow != fast) {
slow = slow.next;
fast = fast.next;
}
return slow;
}
}
return fast;
};