题目描述:给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
分析:
完整代码:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
//在链表中寻找一个节点作为起始点
ListNode* pstart = MeetNode(pHead);
//判断该节点是否存在
if(pstart == nullptr)//如果不存在,则说明链表中不存在环
return nullptr;
/******计算链表中环的长度*******/
//节点的数量
int length = 1;
// 当下位置标记指针
ListNode* pNode = pstart;
//如果当前的节点不是起始点
while(pNode->next != pstart)
{
//一直往下遍历
pNode = pNode->next;
//节点数+1
length++;
}
//*******计算链表中的入口节点*******/
// 创建前指针
ListNode* pNode1 = pHead;
//让前指针先走length步
for(int i = 0; i < length;i++)
{
pNode1 = pNode1->next;
}
//创建后指针
ListNode* pNode2 = pHead;
//判断两指针是否相遇
while(pNode1 != pNode2)
{
//两个节点同步往前走
pNode1 = pNode1->next;
pNode2 = pNode2->next;
}
// 返回环的入口节点
return pNode1;
}
private:
//判断链表中是否存在环
ListNode* MeetNode(ListNode* pHead)
{
//检查输入的合法性
if(pHead == nullptr)
return nullptr; //确保有环
/*******创建快慢指针********/
//创建慢指针
ListNode* pSlow = pHead->next;
//判断慢指针的下一步是否为空
if(pSlow == nullptr)
return nullptr;
//创建快指针
ListNode* pFast =pSlow->next;
/*******让慢指针每次走一步,而快指针每次走两步,如果链表中存在环的话,则两个指针必然会相遇鱼某一节点*******/
//判断快指针和慢指针不为空
while(pFast!= nullptr && pSlow!= nullptr)
{
//如果两指针相遇
if(pFast == pSlow)
return pFast; //返回相遇的节点
//慢指针向前走一步
pSlow = pSlow->next;
//快指针向前走两步
pFast = pFast->next;
//判断快指针是否存在
if(pFast!= nullptr)
{
pFast = pFast->next;
}
}
//如果不存在,则说明不存在环
return nullptr;
}
};