给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
/*
三个问题:
1.判断是否有环:定义两个指针p1,p2。均从头结点出发。p1步幅为1,p2步幅为2。
若在p1到达终点之前p2能追上p1,则有环,否则无环;
2.判断环中结点的个数:在第一步中判断有环的终点处,p1与p2相遇于环内某一点。
这里可以让p1继续向前走知道再次与p2相遇,就可以计算环中结点数量了;
3.判断环的入口在哪:第二步中已知环中的节点数量n,则p1从头结点开始在链表上移动n步,
然后p2在头结点处与p1同步向前走,当两个指针相遇时,p2指向环的入口,而p1已经围绕着环走了一圈又回到了环入口处。
*/
ListNode* MeetingNode(ListNode* pHead)
{
if (pHead == nullptr)
return nullptr;
ListNode* p1 = pHead->next;
if (p1 == nullptr)
return nullptr;
ListNode* p2 = p1->next;
//1.判断是否有环
while (p2 != nullptr && p1 != nullptr)
{
if (p1 == p2)
return p1;
p1 = p1->next;
p2 = p2->next;
if (p2 != nullptr)
p2 = p2->next;
}
return nullptr;
}
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
ListNode* p1 =MeetingNode(pHead);
if (p1 == nullptr)
return nullptr;
ListNode* p2 = p1;
//2.计算环内节点的数量
p1 = p1->next;
int loop_count = 1;
while (p1!=p2)
{
loop_count++;
p1 = p1->next;
}
//3.判断环入口在哪
p1 = pHead, p2 = pHead;
for(int i=0;i<loop_count;i++)
{
p1 = p1->next;
}
while (p1!=p2)
{
p1 = p1->next;
p2 = p2->next;
}
return p1;
}