题目:如果一个链表中包含环,找出环的入口节点。
思考:如果一个链表有环,用一个指针遍历将永远也走不到尽头。若用两个指针遍历:快指针每次走一步,慢指针每次走两步。如果快指针走到了链表的末尾都没有追上慢指针,则没有环。如果快指针追上了慢指针,则有环。
如图:
一个带环的链表,环内节点个数为4.
步骤:
a) 指针pfast,pslow初始化时都指向链表的第一个节点。
b) 由于环中有4个节点,所以pfast指针先走4步。
c) 快指针,慢指针以相同速度向前移动,直到它们相遇。
再思考:
如何得到环中节点的数目?
1)两个指针,快指针一次走两步,慢指针一次走一步,如果俩指针相遇,则说明有环,且相遇的指针一定在环中。
2)设定一个指针从相遇点开始遍历环内节点并计数,待再次回到这个节点时,就可以得到环内节点个数。
如何找到入口节点?
1)两个指针从头遍历,让快指针先走“节点的个数”步,然后快慢指针同时走,待相遇时,即是入口节点。
Node* JudgeIfCircle(Node* pHead)//判断是否有环
{
if(pHead == NULL || pHead->pnext == NULL)
{
return NULL;
}
Node* pfast = pHead->pnext->pnext;
Node* pslow = pHead->pnext;
while(pslow != pfast)
{
pfast = pfast->pnext->pnext;
pslow = pslow->pnext;
}
return pfast;
}
Node* EntryNode(Node* pHead)
{
Node* meetNode = JudgeIfCircle(pHead);
if (meetNode == NULL)
{
return NULL;
}
Node* pCur= meetNode;
/*int count = 0;
while (pCur != meetNode)//循环进不去
{
pCur = pCur -> pnext;
count++;
}*/
int count = 1;
while(pCur->pnext!= meetNode)//查找环中几个节点
{
pCur = pCur->pnext;
count++;
}
Node* pfast = pHead->pnext;
Node* pslow = pfast;//使两个指针指向第一个节点
for (int i = 0; i < count; i++)//快指针先走count步
{
pfast = pfast->pnext;
}
while (pslow != pfast)
{
pfast = pfast->pnext;
pslow = pslow->pnext;
}
return pfast;
}