剑指offer:面试题56——链表中环的入口节点
题目:给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* MeetingNode(ListNode *pHead)
{
if(pHead==NULL) return NULL;
ListNode* pSlow=pHead->next; //定义slow指针和fast指针
if(pSlow==NULL) return NULL;
ListNode* pFast=pSlow->next;
while(pFast!=NULL&&pSlow!=NULL)
{
if(pFast==pSlow) //slow与fast相遇说明链表中存在环
return pFast;
pSlow=pSlow->next;
pFast=pFast->next; //fast每次走的速度比slow快,如果有一方到空则说明没环
if(pFast!=NULL)
pFast=pFast->next;
}
return NULL;
}
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
ListNode* meetingNode=MeetingNode(pHead);
if(meetingNode==NULL) return NULL;
int nodesInLoop=1; //存放环中的节点个数
ListNode* pNode1=meetingNode;
while(pNode1->next!=meetingNode)
{
pNode1=pNode1->next;
++nodesInLoop;
}
pNode1=pHead;
for(int i=0;i<nodesInLoop;i++) //先让Node1走环中节点的步数
pNode1=pNode1->next;
ListNode* pNode2=pHead; //Node2再走这些步,则两者相遇的节点为环的开始节点
while(pNode1!=pNode2)
{
pNode1=pNode1->next;
pNode2=pNode2->next;
}
return pNode1;
}
};