table of Contents:
1. Belt loop problem (determine whether it is belt loop)
(1) Title description
Given a linked list, determine whether there is a ring in the linked list
If there is a node in the linked list that can be reached again by continuously tracking the next pointer, then there is a ring in the linked list. In order to represent the rings in a given linked list, we use the integer pos to indicate the position where the end of the linked list is connected to the linked list (the index starts from 0). If pos is -1, there are no rings in the linked list. Note: pos is not passed as a parameter, just to identify the actual situation of the linked list.
If there is a ring in the linked list, return true. Otherwise, it returns false.
Example 1
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。
Example 2 Language: C language
输入:head = [1], pos = -1
输出:false
解释:链表中没有环。
(2) Idea analysis
This problem can be solved with fast and slow pointers. Two pointers point to the head node of the linked list respectively. The slow pointer goes one node and the fast pointer goes two nodes. When the fast pointer is empty or the next of the fast pointer is empty, there is no loop. If the fast pointer points to the same position as the slow pointer points directly, it proves that the watch has a ring and the two must meet in the ring
a. Question: How to prove that the fast pointer and the slow pointer will meet in the ring instead of missing it all the time?
b. Question: If slow takes one step at a time, fast takes 3 steps at a time? fast 4 steps at a time? fast n steps at a time? Can you catch up?
Conclusion: It may not be able to catch up.
If slow takes one step at a time and fast takes 3 steps at a time, the gap between them is
n-2
n-4
n-6
…
If the gap is 0, it catches up, which is equivalent to slow in place. Fast takes two steps at a time to reduce the gap between the two. It means that if n is an even number, it can catch up, and if n is an odd book, it will be missed. After the most special case is missed, the gap is still odd. Then it will never catch up.
If fast takes 4/5/…/n steps every time, the same principle
(3) Code implementation
bool hasCycle(struct ListNode *head)
{
struct ListNode * slow = head;
struct ListNode * fast = head;
//若fast或fast->next为空不带环
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
//若两个指针指向同一位置,则代换
if(fast == slow)
return true;
}
return false;
}
2. Belt loop problem (return to the point of entry)
(1) Title description
Given a linked list, return the first node where the linked list starts to enter the loop. If the linked list has no rings, NULL is returned
In order to represent the rings in a given linked list, we use the integer pos to indicate the position where the end of the linked list is connected to the linked list (the index starts from 0). If pos is -1, there are no rings in the linked list. Note that pos is only used to identify the ring, and will not be passed to the function as a parameter.
Note: It is not allowed to modify the given linked list.
Example 1 Example 2 Language: C language
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。
输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环。
(2) Idea analysis
Two pointers are given to point to the head node of the linked list, the slow pointer goes one node and the fast pointer goes two nodes. When the fast pointer is empty or the next of the fast pointer is empty, there is no loop. If the fast pointer points to the same position that the slow pointer points directly, it proves that the watch has a ring and the two must meet in the ring. Save the position where the two pointers meet to the pointer meet. At this time, the meet position is away from the node of the ring The position is exactly equal to the position of the head to the node in the ring. At this time, you only need to let meet and head go at the same time. The position where the two meet is the position of the node in the ring.
The diagram is as follows:
(3) Code implementation
struct ListNode *detectCycle(struct ListNode *head)
{
struct ListNode * fast = head;
struct ListNode * slow = head;
//先判断是否带环
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
{
//相遇的节点给meet
struct ListNode * meet = slow;
//带环,给两个指针一个head一个meet,两个指针同时走,直到相遇,相遇点就是入环的节点
while(meet != head)
{
head = head->next;
meet = meet->next;
}
return head;
}
}
return NULL;
}