142. Linked List Cycle II
Difficulty: Medium
Given a linked list, return the node where the cycle begins. If there is no cycle, return null
.
To represent a cycle in the given linked list, we use an integer pos
which represents the position (0-indexed) in the linked list where tail connects to. If pos
is -1
, then there is no cycle in the linked list.
Note: Do not modify the linked list.
Example 1:
Input: head = [3,2,0,-4], pos = 1
Output: tail connects to node index 1
Explanation: There is a cycle in the linked list, where tail connects to the second node.
Example 2:
Input: head = [1,2], pos = 0
Output: tail connects to node index 0
Explanation: There is a cycle in the linked list, where tail connects to the first node.
Example 3:
Input: head = [1], pos = -1
Output: no cycle
Explanation: There is no cycle in the linked list.
Follow up:
Can you solve it without using extra space?
Solution
思路1
使用set
容器(个人经常这样用,汗),遍历set
如果在容器中未找到该结点,将该结点插入,如果找到,返回该结点。
Language: C++
/**
* 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) return head;
set<ListNode*> s;
ListNode* ln = head;
while (ln){
if (s.find(ln) == s.end())
s.insert(ln);
else{
return ln;
}
ln = ln->next;
}
return ln;
}
};
思路2
使用快慢指针,快指针每次走两步,慢指针走一步,如果快慢指针相遇,说明有环,当有环时,慢指针指向head
,然后快慢指针各每次走一步,相遇位置即为环的首结点。
借鉴一下网友的详解:
首先我们看下面这张图:
设:链表头是X,环的第一个节点是Y
,slow
和fast
第一次的交点是Z
。各段的长度分别是a,b,c
,如图所示。环的长度是L。
- 第一次相遇时
slow
走过的距离:a+b
,fast
走过的距离:a+b+c+b
。 - 因为
fast
的速度是slow
的两倍,所以fast走的距离是slow的两倍,有 2(a+b) = a+b+c+b,可以得到a=c (这个结论很重要!)。 - 然后把
slow
移到head
,fast
继续向下走,每次各走一步,因为a=c
,所以相遇即是环的首结点。
/**
* 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) return head;
ListNode* low = head, * fast = head;
while(fast->next && fast->next->next){
low = low->next;
fast = fast->next->next;
if (low == fast){
low = head;
while(low != fast){
low = low->next;
fast = fast->next;
}
return low;
}
}
return NULL;
}
};