1. 如果鏈表中有環,可以通過快慢指針,最後快慢指針肯定會相會於環中的某個節點;
2. 從這個相會的節點開始,當再次遇到該節點,即可統計環中有節點數 n;
3. 設置兩個指針p,p1,p從頭先走 n 步,p1在頭部,然後兩個指針同時 走,當兩指針相遇時,相遇的節點即是環的入口。
C++ 代碼
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
ListNode* getMeetNode(ListNode* pHead) {// 用快慢指針,必然相會於環內某個節點,返回這個節點,否則返回 NULL
if(NULL == pHead) return NULL;
ListNode* pSlow = pHead->next;
if(NULL == pSlow) return NULL;
ListNode* pFast = pSlow->next;
while(pSlow != NULL && pFast != NULL) {
if(pFast == pSlow)
return pFast;
pFast = pFast->next;
pSlow = pSlow->next;
if(pFast != pSlow)
pFast = pFast->next;
}
return NULL;
}
ListNode* EntryNodeOfLoop(ListNode* pHead) {
ListNode* meetNode = getMeetNode(pHead);// 用快慢指針得到環內某個節點
if(NULL == meetNode)
return NULL;
int n = 1;
// 用這個環內節點計算得到環內節點數
ListNode* p = meetNode->next;
while(p != meetNode) {
p = p->next;
++n;
}
// 用兩個指針,一個指針先走環內節點個數的步數,另一個節點在鏈表頭
// 當兩個節點相遇時,此時的節點即是環的入口節點
p = pHead;
while(n--)
p = p->next;
ListNode* p1 = pHead;
while(p1 != p) {
p = p->next;
p1 = p1->next;
}
return p;
}