142. 环形链表 II
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
说明:不允许修改给定的链表。
示例 1:
输入:head = [3,2,0,-4], pos = 1
输出:tail connects to node index 1
解释:链表中有一个环,其尾部连接到第二个节点。
示例 2:
输入:head = [1,2], pos = 0
输出:tail connects to node index 0
解释:链表中有一个环,其尾部连接到第一个节点。
示例 3:
输入:head = [1], pos = -1
输出:no cycle
解释:链表中没有环。
进阶:
你是否可以不用额外空间解决此题?
- 分析
判断环,再到找到入环点;两个指针,一个一次一步,一个一次两步,若有环,则最终都会进入环,速度快的最终会超过速度慢,一定会追上;怎么找到环的入口,直接一个指针从链头,一个从相遇点next,开始一次一步再次相遇的点就是入口。
L+X+n*R=2(L+X)->L=R-X+(n-1)R,即n=1,有L=R-X,从相遇点开始走完剩下的R-X和从表头到环入口距离一样,这样就可以再用两个指针跑一次,相遇的位置即是入口。
具体公式推导见环的入口点 原理理解 - code
/** * Definition for singly-linked list. * type ListNode struct { * Val int * Next *ListNode * } */
func detectCycle(head *ListNode) *ListNode {
var one *ListNode
var two *ListNode
one=head
if head!=nil{
two=head.Next
}else{
two=nil
}
for ;one!=nil&&two!=nil;{
if one==two{
break
}
one=one.Next
if two.Next!=nil{
two=two.Next.Next
}else{
return nil
}
}
if two==nil{
return nil
}
one=head;two=two.Next//一个从头,一个从相遇点,一次一步,则再次相遇就是环开始的点
for one!=nil&&two!=nil{
if one==two{
return one
}
one=one.Next
two=two.Next
}
return nil
}