没看题解前没想到用数学式推导结点关系(当以2倍速差的指针遍历环时,相遇点到环头的距离等于头结点到环头距离)。
我用的一般思维:若有环,则找出环内结点数,重置快慢指针指向头结点,然后使它们之间结点数为环结点数+1,再以相同速度前进,当它们再次相遇时,相遇点就为环头结点。虽然时间复杂度还是O(n),但这样处理会增加一个遍历环找环结点数的时间开销。
/* struct ListNode { int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) { } }; */ class Solution { public: ListNode* EntryNodeOfLoop(ListNode* pHead) { if(!pHead || !pHead->next || !pHead->next->next){//结点数不多于3个且不含环或头结点为空 return NULL; } ListNode *p=pHead,*q=pHead;//p为快指针,q为慢指针 int n=1,flag=0;//记录环内结点数,是否有环 while(p->next->next){ p=p->next->next; q=q->next; if(p==q){//有环 flag=1; p=p->next; while(p!=q){ p=p->next; n++; } break; } } if(!flag){ return NULL; } p=q=pHead;//重置指针,使包含p、q之间结点的长度为环长+1时,p、q重合点即为入环结点 int m=0; while(m<n){ m++; p=p->next; } while(p!=q){ p=p->next; q=q->next; } return p; } };