https://leetcode-cn.com/problems/linked-list-cycle-ii/
思路:
f
l
o
y
d
floyd
floyd判环,一个
s
l
o
w
slow
slow指针,一个
f
a
s
t
fast
fast指针,前者一次一步,后者一次两步。如果后者遇到了
N
U
L
L
NULL
NULL的情况,说明链表无环,否则两者一定会在某个位置相遇。那么我们思考一下怎么求入环节点,先看下图:
下文中的距离表示的是两点之间的边数。我们假设入环节点为
x
x
x,两个指针在
y
y
y相遇,从
h
e
a
d
head
head到
x
x
x的距离为
l
e
n
len
len,从
x
x
x到
y
y
y的距离为
d
i
s
dis
dis,假设环的长度为
L
L
L,
s
l
o
w
slow
slow走过的距离为
d
i
s
_
s
l
o
w
dis\_slow
dis_slow,
f
a
s
t
fast
fast走过的距离为
d
i
s
_
f
a
s
t
dis\_fast
dis_fast,那么易得:
d
i
s
_
s
l
o
w
=
l
e
n
+
d
i
s
dis\_slow=len+dis
dis_slow=len+dis
d
i
s
_
f
a
s
t
=
l
e
n
+
d
i
s
+
k
∗
L
dis\_fast=len+dis+k*L
dis_fast=len+dis+k∗L其中
K
K
K是一个正整数。我们又知道
d
i
s
_
f
a
s
t
=
2
∗
d
i
s
_
s
l
o
w
dis\_fast=2*dis\_slow
dis_fast=2∗dis_slow,将上式化简可得:
l
e
n
=
k
∗
L
−
d
i
s
len=k*L-dis
len=k∗L−dis,也即
d
i
s
+
l
e
n
=
k
∗
L
dis+len=k*L
dis+len=k∗L。那么此时我们再令一个新的指针
c
u
r
=
h
e
a
d
cur=head
cur=head,然后同时移动
c
u
r
、
s
l
o
w
cur、slow
cur、slow,二者相等时的节点就是入环节点。
/**
* 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) {
if(head==NULL)
return NULL;
ListNode *slow=head;
ListNode *fast=head;
while(1){
if(fast->next==NULL)
return NULL;
else
fast=fast->next;
if(fast->next==NULL)
return NULL;
else
fast=fast->next;
slow=slow->next;
if(slow==fast)
break;
}
slow=head;
while(slow!=fast)
slow=slow->next,fast=fast->next;
return slow;
}
};