0%

022.链表中环的入口节点

022. 链表中环的入口节点

题目描述:

给出一个链表head,长度为 $ n $ ,如果存在环,找到环的第一个节点(环的入口);否则返回null。不允许修改链表。

数据范围:
$ 0\le n\le 10^4 $

题解:

使用快慢指针,一个速度为 $ 2 $ ,一个速度为 $ 1 $ ,遍历链表,相遇时证明链表有环。相遇之后将快指针移到链表头,然后继续同时遍历,相遇时就是链表的环入口。

证明:

证明

假设快指针速度为 $ 2v $ ,满指针速度 $ v $ ,则可以得到:

消去 $ vt $ 可以得到:

所以可以得到:

因此可以看出 $ a $ 的长度等于 $ c $ 加若干圈。因此重新将快指针移动到head,再次同时遍历会刚好在环的入口处相遇。

代码:

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
class Solution
{
public:
ListNode *detectCycle(ListNode *head)
{
if (head == nullptr || head->next == nullptr)
return nullptr;
ListNode *fast = head, *slow = head;
while (true)
{
fast = fast->next;
if (fast == nullptr)
return nullptr;
fast = fast->next;
if (fast == nullptr)
return nullptr;
slow = slow->next;
if(slow == fast) break;
}
fast = head;
while (fast != slow)
{
fast = fast->next;
slow = slow->next;
}
return fast;
}
};