没看题解前没想到用数学式推导结点关系(当以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;
    }
};