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;
}