题目链接:
https://leetcode.com/problems/linked-list-cycle-ii/
题意:
给定链表,求是否存在环,如果存在,求出环的入口。
分析:
可以用$map$维护。
更优的话,引用Discuss中的大神的方法——
设一个$slow$和$fast$指针,初始在头结点,$slow$每次跳一个,$fast$每次跳两个。
如果存在环,那么最终$fast$和$slow$肯定会相遇,设相遇除结点为$meeting$,环的入口结点为$entry$。
设$L1$是$head$到$entry$距离,$L2$是$entry$到$meeting$的距离,$C$是环的长度,相遇时$fast$指针在cycle里已经走过$n$圈。
由于$fast$走的路程是$slow$的两倍,因此有$2 \times (L1 + L2) = L1 + L2 + n \times C$,整理后得$L1 + L2 = C$,也就是说从$meeting$出发回到$entry$经过的距离等于从$head$走到$entry$的距离。
同样,对于Find the duplicate number,可以将下标访问看成指针的跳转,将问题转化为求环形链表中是否存在小环。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode *detectCycle(ListNode *head) { if(head == NULL) return head; ListNode* slow = head; ListNode* fast = head; ListNode* entry = head; while(fast->next != NULL && fast->next->next != NULL){ slow = slow->next; fast = fast->next->next; if(slow == fast){ while(slow != entry){ slow = slow->next; entry = entry->next; } return entry; } } return NULL; } };
|