一 题目
对于一个给定的链表,返回环的入口节点,如果没有环,返回null
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
private:
int nodeNum;
public:
ListNode* enterNode(ListNode *head,int numLoop)
{
//定义两个指针p1和p2,初始化为头节点.先让p1走numLoop步,然后p1和p2一起走,相遇时的节点即为入口节点
ListNode* p1 = head;
ListNode* p2 = head;
for(int i=0; i<numLoop; i++){
p1 = p1->next;
}
while(p1 != p2){
p1 = p1->next;
p2 = p2->next;
}
return p1;
//p1 = p1->next;
//p2 = p2->next;
}
ListNode* MeetingNode(ListNode *head)
{
ListNode* pSlow = head->next; //定义并初始化慢指针
if(pSlow->next == NULL) return NULL; //此时链表中一定不存在环
ListNode* pFast = head->next->next;//定义并初始化快指针
while(pFast != NULL && pSlow != NULL){
if(pFast == pSlow) return pFast;//快慢指针相遇,返回相遇的节点
//如果快慢指针不相遇,继续慢指针走一步,快指针走两步,前提:
pSlow = pSlow->next;
pFast = pFast->next;
if(pFast != NULL){//如果pFast==NULL, pFast->next无意义
pFast = pFast->next;
}
}
return NULL;//不存在环
}
ListNode *detectCycle(ListNode *head) {
if(head == NULL) return NULL;
//S1:利用快慢指针判断是否有环
ListNode* meetingNode = MeetingNode(head);
if(meetingNode == NULL) return NULL;
//S2:若有环,统计环中节点的数目
nodeNum = 1;
ListNode* pNode = meetingNode->next;
while(pNode != meetingNode){
nodeNum++;
pNode = pNode->next;
}
//S3:利用双指针定位环的入口节点
ListNode* EnterNode = enterNode(head, nodeNum);
return EnterNode;//返回入口节点
}
};