题目描述:给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
注:常考题目,快慢指针的应用
思路:分两步:
第一步:确定链表是否有环。定义快慢指针:pFast,pSlow;pFast每次走两步,pSlow每次走一步,进行遍历,如果两个指针相遇,即pFast=pSlow,则链表有环,如果pFast达到链表尾部(pFast->next=nullptr)两个指针都没有相遇,则链表没有环。
第二步:找到环的入口。首先确定环中节点的个数n,从第一步快慢指针相遇的节点出发,一边继续向前移动一边计数,当再次回到这个节点时,就可以得到环中节点个数n。然后定义连个指针p1,p2,p1先向前移动n步,p1和p2以相同的速度想想移动,当p2==p1时,即为入口节点。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(pHead==nullptr) return nullptr;
ListNode *pFast=pHead,*pSlow=pHead->next;
//判断是否有环
while(pFast!=nullptr&&pSlow!=nullptr&&pFast!=pSlow){
pSlow=pSlow->next;
pFast=pFast->next;
if(pFast!=nullptr)
pFast=pFast->next;
}
//统计环中的节点数
int cntNum=1;
ListNode *pTemp=pFast->next;
if(pSlow==pFast&&pFast!=nullptr){
while(pTemp!=pFast){
pTemp=pTemp->next;
++cntNum;
}
}
else
return nullptr;
//寻找链表的入口结点
ListNode *pNode1=pHead,*pNode2=pHead;
for(int i=0;i<cntNum;++i){
pNode1=pNode1->next;
}
while(pNode2!=pNode1){
pNode2=pNode2->next;
pNode1=pNode1->next;
}
return pNode1;
}
};