题目描述
一个链表中包含环,请找出该链表的环的入口结点。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
}
};
粗暴方法,供出利器map
:
/*
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;
map<ListNode*, int> cnt;
while(pHead != NULL)
{
cnt[pHead]++;
if(cnt[pHead] == 2)
return pHead;
pHead = pHead->next;
}
return NULL;
}
};
烧脑解法:
- 第一步: 找环中相汇点。分别用p1,p2指向链表头部,p1每次走一步,p2每次走二步,直到p1==p2找到在环中的相汇点。
- 第二步: 找环的入口。接上步,当p1p2时,p2所经过节点数为2x, p1所经过节点数为x,设环中有r个节点, p2比p1多走 n (n >= 1)圈. 有2x=nr+x; 可以看出p1实际走了n个环的步数,再让p2指向链表头部,p1位置不变,p1,p2每次走一步直到p1p2; 此时p1和 p2指向环的入口.
简单证明:
设起点到相遇点距离为x,起点到入口点距离为y,环长度为r, 则快慢指针相遇时,满足2x-x=nr,n为快指针在环中转的圈数。于是 x=nr 快慢指针相遇点距环入口点距离 x-y(正负没关系) 。相遇后,快指针从起点重新开始以步长为1速度开始走,经过距离y到达环入口点,慢指针走y步后距离环入口点距离为 x-y+y = x = nr,即走到了环入口点,两个指针相遇!
/*
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* fastPos = pHead;
ListNode* slowPos = pHead;
while(fastPos != NULL && slowPos != NULL)
{
if(fastPos->next != NULL)
{
fastPos = fastPos->next;
fastPos = fastPos->next;
}
else
return NULL;
slowPos = slowPos->next;
if(slowPos == fastPos)
break;
}
if(fastPos == NULL || slowPos == NULL)
return NULL;
fastPos = pHead;
while(fastPos != slowPos)
{
fastPos = fastPos->next;
slowPos = slowPos->next;
}
return fastPos;
}
};