Ring Linked List Entry
Table of Contents
Main
确认是否环形链表,只需要使用快慢指针就可以轻松解决。但是确认环形链表的入口就有一点复杂了,不需要增加新的技巧,但是却有一个神奇的数学规律。
判断环形链表
struct Node { int val; Node *next; } bool detectCycle(Node *head) { if (head == nullptr || head->next == nullptr) return nullptr; Node *slow = head; Node *fast = head; while (fast != nullptr && fast->next != nullptr) { fast = fast->next->next; slow = slow->next; if (fast == slow) return true; } return false; }
寻找环形链表的入口
这里有一个非常关键的代码, fast 指针一次移动两个节点,巧妙之处在后文会体现。
Denoted
- \( x \) is the length from head to entry of ring linked list.
- \( y \) is the length from entry to encounter point of slow and fast pointer.
- \( z \) is the length from encounter pointer to entry.
- \( a \) is distance of slow pointer had pasted.
- \( b \) is distance of fast pointer had pasted.
So that, we has,
\begin{equation} \label{eq:1} a = x + y \end{equation} \begin{equation} \label{eq:2} b = x + y + n \cdot (y+z) \end{equation} \begin{equation} \label{eq:3} b = 2a \end{equation}As a result, we got,
\begin{equation} \label{eq:4} 2 \cdot (x+y) = x+ y + n \cdot (y+z) \end{equation}which means,
\begin{equation} \label{eq:5} x = z + (n-1)(y+z) \end{equation}and \( y+z \) is the length of ring. so if we set a new pointer at head, step one per time with slow pointer, then will encounter at the entry!!!
struct Node { int val; Node *next; } Node *detectCycle(Node *head) { if (head == nullptr || head->next == nullptr) return nullptr; Node *slow = head; Node *fast = head; while (fast != nullptr && fast->next != nullptr) { fast = fast->next->next; slow = slow->next; if (fast == slow) { Node *node = head; while (node != slow) { node = node->next; slow = slow->next; } return node; } } return nullptr; }
如果快指针一次不止移动两步
Assumed that fast pointer move \( k \) step per time, then we got
\(\)\[ (k-1)(x+y) = n \cdot (y+z) \] \[ x = z + \frac{1-k+n}{k-1} (y+z) \]
可以发现这个时候 \( x, z \) 的差值不一定是环形的长度的整数倍了。