题目描述
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
思路:方法1.直接用哈希表,遇到地址相同时返回即可。
2.先判断有没有环,如果有环则需要找到入口。
判断有没有环比较简单,直接用两个指针,一个走两步,一个走一步,如果有环,则它们肯定会在环里相遇。
主要找入口节点麻烦点,这里我们可以举个例子,如下图,就是存在一个环,如果我们知道这个环的长度为4,那么我们便可以在一开始设置两个指针,一个指针从a出发,一个指针先移动4位,即移动到e上,这样两个指针同时走,行进长度都为1,如下:
第一个指针:a - b - c - d
第二个指针:e - f - g - d
我们可以看出,由于第一个指针和第二个指针的长度相差一个环,所以肯定在环的入口相遇。因为第一个指针刚到入口,第二个指针已经走了一圈了。那么如何求长度呢,主要依靠上面找环的方法,当存在环时,记录当前地址计数,当回到原地址时,计数便能得到环的长度。
方法1:哈希
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(pHead == NULL || pHead->next == NULL)
return NULL;
unordered_map<ListNode*,int>ans;
while(pHead)
{
ans[pHead] += 1;
if(ans[pHead] == 2)
return pHead;
pHead = pHead->next;
}
return NULL;
}
};
方法二:求是否存在环——若存在,求环长——求入口地址
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(pHead == NULL || pHead->next == NULL)
return NULL;
if(pHead->next == pHead)//环就是头节点自身
return pHead;
if(checkList(pHead) == NULL)//无环
return NULL;
ListNode* myNode = checkList(pHead)->next;
int count = 1;
while(myNode != checkList(pHead))//进行计数
{
count++;
myNode = myNode->next;
}
ListNode* p1 = pHead;
ListNode* p2 = pHead;
for(int i = 0; i<count; i++)// p2移动n位
p2 = p2->next;
while(p1 != p2)
{
p1 = p1->next;
p2 = p2->next;
}
return p1;
}
ListNode * checkList(ListNode* pHead)
{
ListNode* myHead = pHead->next->next;
pHead = pHead->next;
while(myHead)
{
if(myHead == pHead);
return myHead;
pHead = pHead->next;
myHead = myHead->next->next;
}
return NULL;
}
};