給一個鏈表,若其中包含環,請找出該鏈表的環的入口結點,否則,輸出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;
}
};