方法1:哈希表
使用map判断当前节点是否存在于map中,直到找到重复结点或者链表遍历完
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func detectCycle(head *ListNode) *ListNode {
slice := map[*ListNode]int{}
for {
if head == nil{
return nil
}
if _,ok := slice[head]; ok {
return head
}
slice[head] = 1
head = head.Next
}
}
方法二:快慢指针
我们设置两个指针,slow,fast,都位于起始地点,slow指针每次移动一个结点,fast每次两个,如果存在环,则两个指针会在环里相遇,并且是在slow指针循环第一遍环的时候相遇。
此时设fast在环中转了n圈
fast走的距离: a + (b+c)*n +b
slow走到距离: a + b
其中fast走到距离等于二倍的slow的距离
即:(a + b)*2 == a + (b+c)*n + b
推导等式得: a == (b+c)*n - b
也就是 a的长度等于 n圈之后减一个b,所以当fast与slow相遇的时候我们在链表的头结点再设置一个指针item,一次移动一个结点,最终会和slow指针在环的入口处相遇 。
当然我们也可以将等式写为 a == (b+c)x(n-1)+c
即slow在走(n-1)圈之后再走c的距离与item指针在入口处相遇。
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func detectCycle(head *ListNode) *ListNode {
var ans,slow,fast *ListNode
slow,fast = head,head
for fast != nil{
if fast.Next == nil {
break
}
fast = fast.Next.Next
slow = slow.Next
if fast == slow {
ans = head
for ans != slow{
ans = ans.Next
slow = slow.Next
}
break
}
}
return ans
}