一、思路
分两步:
第一步,判断有没有环。判断链表是否有环,可以用快慢指针的方法,慢指针一次走一个节点,快指针一次走两个节点,若果快慢指针会相遇,则一定存在环。
第二步,找到入口。假设头结点到环入口的节点数为
x
x
x,环入口到相遇点的节点数为
y
y
y,相遇点到环入口的距离为
z
z
z,如下图所示。
slow走过的节点数为
x
+
y
x+y
x+y
fast走过的节点数为
x
+
y
+
n
(
y
+
z
)
x+y +n(y+z)
x+y+n(y+z)
fast走过的节点数还是slow的2倍,所以可以得到方程,
2
(
x
+
y
)
=
x
+
y
+
n
(
y
+
z
)
2(x+y)= x+y+n(y+z)
2(x+y)=x+y+n(y+z)
x
+
y
=
n
(
y
+
z
)
x+y =n(y+z)
x+y=n(y+z)
当
n
=
1
时
,
x
=
z
当n=1时,x=z
当n=1时,x=z,,
我们可以令index1在头结点开始出发,index2在相遇点出发,index1和index2相遇的地点,就是环的入口。
当
n
>
1
时
,
x
=
n
(
y
+
z
)
−
y
−
z
+
z
=
(
n
−
1
)
(
y
+
z
)
+
z
当n>1时,x = n(y+z)-y-z+z = (n-1)(y+z) +z
当n>1时,x=n(y+z)−y−z+z=(n−1)(y+z)+z,同上,x走的距离要在环内多转 n-1圈,所以,和n=1的情况是一样的。
二、代码
1.python
代码如下:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def detectCycle(self, head) :
slow, fast = head, head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if fast == slow:
index1, index2 = head, fast
while (index1 != index2):
index1 = index1.next
index2 = index2.next
return index2
return -1
2.C++
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *slow = head, *fast = head;
while(fast != NULL && fast->next != NULL){
slow = slow->next;
fast = fast->next->next;
if(slow == fast){
ListNode *index1 = head, *index2 = fast;
while(index1 != index2){
index1 = index1->next;
index2 = index2->next;
}
return index2;
}
}
}
};