题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出 n u l l null null。
思路:
1)首先利用快慢指针判断是否有环,如果无环则返回null,有环则进行下一步操作
2)如果有环,即可看作下图的示例,假设
A
B
AB
AB段即环外的长度为
L
L
L,
B
P
BP
BP段即从进入环到交点的长度为
x
x
x,整个环的长度设为
m
m
m;假设慢指针在环中所走的圈数为
t
t
t,快指针所走的圈数为
k
k
k,那么慢指针所走的距离即为
L
+
t
m
+
x
L+ tm + x
L+tm+x,快指针所走的距离即为
L
+
k
m
+
x
L + km + x
L+km+x,因为快指针所走的距离为慢指针所走距离的两倍,所以有
L
+
k
m
+
x
=
2
(
L
+
t
m
+
x
)
−
−
>
L
=
(
k
−
2
t
)
m
−
x
=
(
k
−
2
t
−
1
)
m
+
m
−
x
L + km + x = 2(L + tm + x) -->L = (k - 2t)m - x = (k - 2t - 1)m + m - x
L+km+x=2(L+tm+x)−−>L=(k−2t)m−x=(k−2t−1)m+m−x
即
L
L
L相当于从
p
p
p走到
B
B
B然后再走
k
−
2
t
−
1
k - 2t - 1
k−2t−1圈环,那么我们可以让慢指针从
p
p
p开始走
L
L
L段距离,那么其最后会在
B
B
B点即环入口,那么如何确定该
L
L
L的大小呢?
我们可以让一个指针从
A
A
A走到
B
B
B,这段距离即为
L
L
L,让慢指针与该指针一同出发,相等时即为环入口
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
ListNode* pFast = pHead;
ListNode* pSlow = pHead;
while (pFast != nullptr && pFast->next != nullptr) {
pFast = pFast->next->next;
pSlow = pSlow->next;
if (pFast == pSlow)
break;
}
if (pFast == nullptr || pFast->next == nullptr)
return nullptr;
pFast = pHead;
while (pFast != pSlow) {
pFast = pFast->next;
pSlow = pSlow->next;
}
return pFast;
}
};