题目描述
一个链表中包含环,请找出该链表的环的入口结点。
思路一:使用一个集合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; } };