每日一题
链表中环的入口节点
题目链接

思路(双指针法)
- 第一步:第一步当然是判断该链表是否存在环。由昨天的题目判断链表是否有环,可以很简单的进行判断
- 第二步:即找到环的入口节点。
- 我们可以在第一步中可以得到快慢指针相遇的节点位置,可以设相遇节点到头节点的距离为X,环入口节点到相遇节点的距离为Y(从左到右),相遇节点到环入口节点的距离为Z(从右到左),如此图中,X = 2, Y = 2, Z = 2
- 如图:

- 由分析可得:当快慢指针相遇时,慢指针slow一共走了X + m(Y + Z) + Y个节点,快指针fast一共走了X + n(Y + Z) + Y个节点,我们预定快指针fast每次比慢指针slow多走一个节点,则X + n(Y + Z) + Y = 2(X + m(Y + Z) + Y),即X + Y = (n - 2m)(Y + Z),即X = (n - 2m - 1)(Y + Z) + Z。
- 我们可以再定义连个指针index1,index2,令index1指向链表头,index2指向快慢指针相遇的节点,并每次让index1,index2每次一起走一个节点,由X = (n - 2m - 1)(Y + Z) + Z可知,index1走到环入口节点所走过的节点数恰好等于index2走到环入口节点所走过的节点数加上整数倍环的节点数,即当index1与index2相遇的点即为环的入口节点。
实现代码
struct ListNode * Judge_Loop(struct ListNode *pHead)
{
if(!pHead)
return NULL;
struct ListNode*fast,*slow;
fast = slow = pHead;
while(slow && fast)
{
slow = slow->next;
if(!fast->next)
return NULL;
fast = fast->next->next;
if(fast == slow)
return fast;
}
return NULL;
}
struct ListNode* EntryNodeOfLoop(struct ListNode* pHead ) {
if(!Judge_Loop(pHead))
return NULL;
struct ListNode* index1 = pHead;
struct ListNode* index2 = Judge_Loop(pHead);
while(1)
{
if(index1 == index2)
return index1;
index1 = index1->next;
index2 = index2->next;
}
}