第五题 第一种 利用hash函数
/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead) {
        map<ListNode *,int> hash;
        // 利用的map 的hash函数
        // 出现过 就hash记录下来,每次判断是不是之前出现过
        ListNode* p=pHead;
        while(p!=NULL)
        {
            if (hash[p])
                return p;
            hash[p]=1;
            p=p->next;
        }
        return NULL;
    }
};


第二种 快慢指针
/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead) {
        // 常见的做法 利用快慢指针判断是否有环
        // 相遇了 再找结点
        
        // 边界问题
        if (pHead == NULL || pHead->next == NULL )
            return NULL;
        
        // 两个快慢指针
        ListNode*p=pHead;
        ListNode*q=pHead;
        
        // 第一次循环 判断是否有环
        while(p!=NULL)
        {
            p=p->next->next;
            q=q->next;
            if(p==q)
                break;
        }
        
        // 如果没有环。p就是到了NULL结束的
        if (p==NULL)
            return NULL;
        
        // q回到开头重新开始 找到环开始的地方
        q=pHead;

        // 数学原理 我是记住了的。。。
        // 原理百度一下
        // https://blog.csdn.net/qq_43676757/article/details/109264389
        while(p!=q)
        {
            p=p->next;
            q=q->next;
        }
        return p;
    }
};