先判断链表是否有环。设置快慢指针,若快慢指针相遇,则链表有环。返回快慢指针相遇的节点。
若有环,求环的节点数目k。设置指针,起点终点都为快慢指针相遇的节点,走一圈经过的节点数目,就是环的节点数目。
之后再设置快慢指针,快指针领先k个节点。快慢指针相遇时,相遇节点即为环的入口节点。
#include<iostream>
using namespace std;
struct ListNode
{
int val;
struct ListNode *next;
};
//判断链表是否有环。有环返回快慢指针相遇的节点,无环返回空。
ListNode* MeetingNode(ListNode* pHead)
{
if (pHead == NULL)
return NULL;
ListNode* pSlow = pHead;
ListNode* pFast = pHead->next;
if (pFast == NULL)
return NULL;
while (pFast != NULL && pSlow != NULL)
{
if (pFast == pSlow)
return pFast;
pSlow = pSlow->next;
pFast = pFast->next;
if (pFast != NULL)
pFast = pFast->next;
}
return NULL;
}
//求环的节点数目,再求环的入口节点
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,次数为环中结点的数目
pNode1 = pHead;
for (int i = 1; i <= nodesInLoop; i++)
{
pNode1 = pNode1->next;
}
// 再移动pNode1和pNode2,pNode1和pNode2相遇的节点就是入口节点
ListNode* pNode2 = pHead;
while (pNode1 != pNode2)
{
pNode1 = pNode1->next;
pNode2 = pNode2->next;
}
return pNode1;
}
int main()
{
//无环的链表
ListNode *head =NULL;
ListNode *end =NULL;
for (int i = 1; i <= 5; i++)
{
ListNode *p = (ListNode *)malloc(sizeof(ListNode));
p->val = i;
p->next = NULL;
if (head == NULL)
{
head = p;
end = p;
}
else
{
end->next = p;
end = p;
}
}
//有环的链表
ListNode *head2 = NULL;
ListNode *end2 = NULL; //尾指针
for (int i = 1; i <= 5; i++)
{
ListNode *p = (ListNode *)malloc(sizeof(ListNode));
p->val = i;
p->next = NULL;
if (head2 == NULL)
{
head2 = p;
end2 = p;
}
else
{
end2->next = p;
end2 = p;
}
}
end2->next = head2->next->next;//构成环
ListNode *p;
p = EntryNodeOfLoop(head2);
cout << p->val << endl;
}