版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/isluckyguo/article/details/84278423
问题:如果一个链表中包含环,如何找出环的入口节点?如下图链表中,环的入口节点是节点3.
解题思路:第一步是如何确定一个链表中是否包含一个环,也可以采用两个指针来解决,定义两个指针,同时从链表的头节点出发,一个指针一次走一步,另一个指针一次走两步,如果走的快的指针追上了走的慢的指针,那么链表中就包含环,如果走的快的指针走到链表末尾了(m_pNext==nullptr)都没追上走的慢的指针,那么链表中就不存在环。第二步是要确定环的入口,同样利用两个指针,先定义两个指针P1,P2指向链表头节点,如果链表中的环有n个节点,则指针P1先在链表上向前移动n步,然后两个指针以相同的速度向前移动,当第二个指针指向环的入口节点时,第一个指针已经围绕环走了一圈,又回到了入口节点。 那么如何得到环中节点的数目,前面判断链表中是否有环用到两个指针,如果两个指针相遇则说明链表中有环,而且两个指针相遇的节点一定是在环中,那么从这个节点出发,一边继续向前移动一边计数,当再次回到这个节点时,就可以得到环中节点数了。
ListNode *MeetingNode(ListNode *pHead)
{
if(pHead == nullptr)
return nullptr;
ListNode *pSlow = pHead->m_pNext;
if(pSlow == nullptr)
return nullptr;
ListNode *pFast = pSlow->m_pNext;
while(pFast != nullptr && pSlow != nullptr)
{
if(pFast == pSlow)
return pFast;
pSlow = pSlow->m_pNext;
pFast = pFast->m_pNext;
if(pFast != nullptr)
pFast = pFast->m_pNext;
}
return nullptr;
}
ListNode *EntryNodeOfLoop(ListNode *pHead)
{
ListNode *meetingNode = MeetingNode(pHead);
if(meetingNode == nullptr)
return nullptr;
int numNodeInLoop = 1;
ListNode *pNode1 = meetingNode;
while(pNode1->m_pNext != meetingNode)
{
pNode1 = pNode1->m_pNext;
numNodeInLoop++;
}
pNode1 = pHead;
for(int i=0; i<numNodeInLoop; i++)
pNode1 = pNode1->m_pNext;
ListNode *pNode2 = pHead;
while(pNode1 != pNode2)
{
pNode1 = pNode1->m_pNext;
pNode2 = pNode2->m_pNext;
}
return pNode1;
}