55.链表中环的入口结点

题目描述

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


思路一:使用一个集合unordered_set<ListNode*>来保存已经访问过的结点,当第一次访问到已经被访问过的结点时,即为环的入口结点,此方法需要额外的空间进行辅助。


代码一:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead) {
        ListNode* res;
        while(pHead != NULL) {
            if(map.find(pHead) == map.end()) {
                map.insert(pHead);
            } else {
                res = pHead;
                break;
            }
            pHead = pHead->next;
        }
        return res;
    }
private:
    unordered_set<ListNode*> map;
};

思路二:

采用数学分析的方法,设置快慢指针,慢指针每次前进一个结点,快指针每次前进两个结点,记相遇时的结点为q,则从q到环入口的距离与从头结点到入口的距离相等,此时从头结点和q处同时往后移动,每一移动一个结点,则相遇处即为环的入口,此方法不需要开辟额外的存储空间,更佳。


代码二:

/*
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* slow = pHead;
        ListNode* fast = pHead;
        while(slow && fast && fast->next){
            slow = slow->next;
            fast = fast->next->next;
            if(slow == fast) break;
        }
        if(fast == NULL || fast->next == NULL) return NULL;  //不存在环的情况
        slow = pHead;
        while(slow && fast){
            if(fast == slow) return fast;  //先进行判断,因为存在交点即为入口的情况
            fast = fast->next;
            slow = slow->next;
        }
        return NULL;
    }
};

猜你喜欢

转载自blog.csdn.net/nichchen/article/details/80514932