时间复杂度:O(n),空间复杂度:O(1)
解题思路
还是用快慢指针判断链表是否有环,但是如何确定环形链表的第一个结点呢?
首先将一个链表拆成三部分:
- x1:x1表示从链表的head到环形链表的入口结点的长度
- x2:x2表示从环形链表的入口结点到快慢指针第一次相遇结点的长度
- x3:x3表示快慢指针第一次相遇的结点到下一次到入口结点的长度
我们在小学都学过追击问题,快慢指针的速度差为1,所以当快慢指针第一次相遇时快指针刚好比慢指针多走了一个环形链表的长度。这样我们便可以在快慢指针第一次相遇时根据时间相同列出等式:
(x1+x2+x3+x2)/2=x1+x2
即x1=x3
而x3刚好是慢指针走到入口结点的距离,所以我们让快指针回到head每次走一步,慢指针照老样子继续走,当二者再次相遇时的结点就是我们要找的环形链表的入口结点。
AC代码
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func detectCycle(head *ListNode) *ListNode {
slow,fast:=head,head
for fast!=nil&&fast.Next!=nil{
slow=slow.Next
fast=fast.Next.Next
if slow==fast{
fast=head
//下一次相遇的结点就是环形链表的第一个节点
for slow!=fast{
slow=slow.Next
fast=fast.Next
}
return fast
}
}
return nil
}
感悟
只能想到用哈希表记录遍历过的结点,以及用快慢指针的思路判断环,但是没有细细推敲快慢指针遍历时走过的长度关系。