链表中环的入口
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
思路
第k个,倒数,环的大小等等,都使用两个有一定距离的指针!
- 判断链表是否有环
- 一个指针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;
int loopLen = 0;
if(!isExistLoop(pHead, loopLen))
return nullptr;
else
{
ListNode* pAhead = pHead;
ListNode* pBehind = pAhead;
while(loopLen--)
pAhead = pAhead->next;
while(pAhead!=pBehind)
{
pAhead = pAhead->next;
pBehind = pBehind->next;
}
return pAhead;
}
}
bool isExistLoop(ListNode* pHead, int &loopLen)
{
loopLen = 0;
ListNode* pAhead = pHead;
ListNode* pBehind = pAhead;
while(true)
{
if(pAhead->next!=nullptr && pAhead->next->next!=nullptr)
{
pAhead = pAhead->next->next;
}
else
{
return false;
}
pBehind = pBehind->next;
if(pAhead == pBehind)
break;
}
while(true)
{
pAhead = pAhead->next;
++loopLen;
if(pAhead == pBehind)
break;
}
return true;
}
};