题目:给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
第一步,找环中相汇点。分别用p1,p2指向链表头部,p1每次走一步,p2每次走二步,直到p1==p2找到在环中的相汇点。
第二步,找环的长度。从环中的相汇点开始, p2不动, p1前移, 当再次相遇时,p1刚好绕环一周, 其移动即为环的长度K
第三步, 求环的起点, 转换为求环的倒数第N-K个节点,则两指针left和right均指向起始, right先走K步, 然后两个指针开始同步移动, 当两个指针再次相遇时, right刚好绕环一周回到起点, left则刚好走到了起点位置
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(pHead==NULL)return NULL;
//先计算环中结点的个数
//快慢指针相遇结点一定在环中
ListNode *pFast=pHead,*pSlow=pHead->next;
while(pFast!=NULL&&pSlow!=NULL&&pFast!=pSlow){
pSlow=pSlow->next;
pFast=pFast->next;
if(pFast!=NULL)
pFast=pFast->next;
}
//开始统计环结点数
int countNum=1;
ListNode *pTempNode=pFast->next;
if(pFast==pSlow&&pFast!=NULL){
while(pTempNode!=pFast){
pTempNode=pTempNode->next;
++countNum;
}
}
else
return NULL;//链表不存在环
//再设两指针,一先一后,找出环的入点
ListNode *pNode1=pHead,*pNode2=pHead;
for(int i=0;i<countNum;i++){
pNode1=pNode1->next;
}
while(pNode1!=pNode2){
pNode1=pNode1->next;
pNode2=pNode2->next;
}
return pNode1;
}
};