给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
思路:
- 确定一个链表中是否存在环,用快慢指针法:走的快的指针追上了走得慢的指针,则存在环
- 得到环中节点的数目。两个指针相遇的节点一定位于环内,可以从这个相遇的节点出发,一边移动一边计数直到再次回到该节点
- 找到环的入口:两个指针p1,p2都先指向表头,如果链表中的环有n个节点,则指针p1先移动n步,然后两个指针一相同的速度移动,直到它们相遇,相遇的节点就是环的入口。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def EntryNodeOfLoop(self, pHead):
# write code here
MettingNode=self.MettingNode(pHead)
if MettingNode==None:
return None
nodesInLoop=1
pNode1=MettingNode
while pNode1.next!=MettingNode:
nodesInLoop+=1
pNode1=pNode1.next
#先移动pNode1
pNode1=pHead
for i in range(nodesInLoop):
pNode1=pNode1.next
#再一起移动
pNode2=pHead
while pNode1!=pNode2:
pNode1=pNode1.next
pNode2=pNode2.next
return pNode1
def MettingNode(self,pHead): #找到快慢指针相遇点
if pHead==None:
return None
pSlow=pHead.next
if pSlow==None:
return None
pFast=pSlow.next
while pFast!=None and pSlow!=None:
if pFast==pSlow:
return pFast
pSlow=pSlow.next
pFast=pFast.next
if pFast!=None:
pFast=pFast.next
return None
c++版本:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
ListNode* MeetingNode=MeetingNode(pHead); //快慢指针相遇点
if(MeetingNode==nullptr)
return nullptr;
int nodesInLoop=1;
ListNode* pNode1=MeetingNode;
while(pNode1->next != MeetingNode)
{
pNode1=pNode1->next;
++pNode1;
}
//先移动pNode1
pNode1=pHead;
for(int i=0;i<nodesInLoop;i++)
pNode1=pNode1->next;
//再一起移动
ListNode* pNode2=pHead;
while(pNode1 != pNode2)
{
pNode1=pNode1->next;
pNode2=pNode2->next;
}
return pNode1;
}
ListNode* MeetingNode(ListNode* pHead)
{
if(pHead==nullptr)
return nullptr;
ListNode* pSlow=pHead->next;
if(pSlow==nullptr)
reutrn nullptr;
ListNode* pFast=pSlow->next;
while(pSlow!=nullptr && pFast!=nullptr)
{
if(pFast==pSlow)
return pFast;
pSlow=pSlow->next;
pFast=pFast->next;
if(pFast!=nullptr)
pFast=pFast->next;
}
return nullptr;
}
};