链表中环的入口结点

题目描述

一个链表中包含环,请找出该链表的环的入口结点。

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {

    }
};

题目链接

粗暴方法,供出利器map:
/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        if(pHead == NULL)
            return NULL;
        map<ListNode*, int> cnt;
        while(pHead != NULL)
        {
            cnt[pHead]++;
            if(cnt[pHead] == 2)
                return pHead; 
            
            pHead = pHead->next; 
        }
        
        return NULL; 
    }
};




烧脑解法:
  • 第一步: 找环中相汇点。分别用p1,p2指向链表头部,p1每次走一步,p2每次走二步,直到p1==p2找到在环中的相汇点。
  • 第二步: 找环的入口。接上步,当p1==p2时,p2所经过节点数为2x, p1所经过节点数为x,设环中有r个节点, p2比p1多走 n (n >= 1)圈. 有2x=nr+x; 可以看出p1实际走了n个环的步数,再让p2指向链表头部,p1位置不变,p1,p2每次走一步直到p1==p2; 此时p1和 p2指向环的入口.
简单证明:

设起点到相遇点距离为x,起点到入口点距离为y,环长度为r, 则快慢指针相遇时,满足2x-x=nr,n为快指针在环中转的圈数。于是 x=nr 快慢指针相遇点距环入口点距离 x-y(正负没关系) 。相遇后,快指针从起点重新开始以步长为1速度开始走,经过距离y到达环入口点,慢指针走y步后距离环入口点距离为 x-y+y = x = nr,即走到了环入口点,两个指针相遇!

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    {
        if(pHead == NULL)
            return NULL; 
        ListNode* fastPos = pHead; 
        ListNode* slowPos = pHead;
        while(fastPos != NULL && slowPos != NULL)
        {
            if(fastPos->next != NULL)
            {
                fastPos = fastPos->next; 
                fastPos = fastPos->next; 
            }
            else
                return NULL; 
            
            slowPos = slowPos->next; 
            
            if(slowPos == fastPos)
                break;
        }
        
        if(fastPos == NULL || slowPos == NULL)
            return NULL;
        
        fastPos = pHead; 
        while(fastPos != slowPos)
        {
            fastPos = fastPos->next; 
            slowPos = slowPos->next; 
        }
        
        return fastPos; 
    }
};




posted @ 2017-06-20 21:56  草滩小恪  阅读(...)  评论(... 编辑 收藏