题目描述
给定一个长度为n的链表,若其中包含环,请找出该链表的环的入口结点,否则返回空值。
示例
输入:head = [3,2,0,-4]
输出 :tail connects to node index 1(这个输出表示该链表中环的入口结点为索引为1的结点 )
算法思路
- 首先,确认该链表中是否存在环:通过设置两个指针slow和fast,slow指针每次走一步,而fast指针每次走两步,当这两个指针相等时,则表明存在环(因为fast每次移动不能超过两步,所以存在环的话两个指针就会相遇)。
- 注意相遇时的结点并非就是环的入口,要想确定环的入口,需要利用相遇时的结点信息:(1)假设头结点距离环的入口点有H步,入口点到第一次相遇点有D步,环的一圈为C步;(2)第一次相遇时假设fast指针相对于入口点转了n圈,那么第一次相遇时,slow指针运动了(H+D)步,fast指针运动了(H+nC+D);(3)因为fast是slow的两倍速度,则有2(H+D)=H+nC+D,进一步得出:H = nC-D;(4)所以我们设置一个entry指针从头结点出发,而fast或slow指针以同样的速度从第一次相遇的位置出发,H步后,会在入口点相遇。
代码实现
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
slow = head
fast = head
entry = head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if slow == fast:
# 利用相遇后的信息寻找入口点
while entry != slow:
entry =entry.next
slow = slow.next
return entry
return None