Given a linked list, determine if it has a cycle in it. Follow up: Can you solve it without using extra space?
The question is to use the space of O (1) to determine whether a linked list has a ring. In my first thought, every time I access a node, I traverse all the nodes in front of the node and determine if they are the same. If they are the same, there is a ring. If all the nodes have been accessed and no identical nodes are found, the linked list has no loops. However, this idea will soon be destroyed because the complexity of this algorithm will reach O (N ^ 2), which is too slow! Later, I thought of using two pointers, one fast and one slow. If there is a ring, these two pointers will certainly meet each other. This method does not require extra space and the complexity is O (n. Meets the requirements of this question. Specifically, it is to set up two pointers, one fast and one slow. Fast moves two steps in each step, and slow moves one step at a time. If the two meet each other, there must be a ring. At the same time, fast will slow ring. This problem is easily solved. The specific implementation code is as follows.
class Solution {public: bool hasCycle(ListNode *head) { if(!head || !head->next) return false; ListNode *fast,*slow; fast = slow = head; bool flag = false; while(fast) { fast = fast->next; if(flag) { slow = slow->next; flag = false; } else { flag = true; } if(fast == slow) return true; } return false; }};
Given a linked list, return the node where the cycle begins. If there is no cycle, returnnull
. Follow up: Can you solve it without using extra space?
Linked List cycle II not only requires judging whether a ring exists, but also needs to find the starting node of the ring when the ring exists. This is more difficult than I. At first, I thought of a method similar to the question: fast, moving two steps, one slow, and one step at a time. The two pointers must not only move forward, but also record the number of steps (fastcount and slowcount) they take ). When the encounter occurs, fastcount minus slowcount is the length of the change (assuming the length of Len ). In this case, let fast and slow point to the head node again. Then let the fast pointer move the Len step forward. Then fast and slow move at the same time, and both move one step at a time. When the two met, they were actually nodes of the ring. The Code is as follows:
class Solution {public: ListNode *detectCycle(ListNode *head) { if(!head || !head->next) return NULL; ListNode *fast,*slow; int fastCount = 1,slowCount = 1; bool hasCycle = false, flag = false; fast = slow = head; while(fast) { fast = fast->next; ++fastCount; if(flag) { slow = slow->next; ++slowCount; flag = false; } else { flag = true; } if(fast == slow) { hasCycle = true; break; } } if(!hasCycle) return NULL; int cycleLen = fastCount - slowCount; fast = slow = head; for(int i = 0; i < cycleLen; ++i) fast = fast->next; while(true) { if(fast == slow) return slow; fast = fast->next; slow = slow->next; } }};
However, after referring to others' algorithms, we found that this algorithm can be more streamlined. Let's take a look at the figure below.
P1 is the Start Node of the ring, and P2 is the node where the fast pointer and the slow pointer meet. The distance between A, B, and C is three segments. When the slow pointer passes through (a + B) while the fast pointer passes through (A + B + C + B ). At the same time, fast is twice the distance of slow, so (A + B + C + B) = 2 (A + B), so finally we get a = C! When the two meet each other, you only need to put the slow pointer back to the starting node, and the fast pointer continues to move forward in the original position. The two pointers share the same speed to access the node. When the two encounter again, the encounter node is the starting node P1 of the loop. The implementation code is as follows:
class Solution {public: ListNode *detectCycle(ListNode *head) { if(!head || !head->next) return NULL; ListNode *fast,*slow; fast = slow = head; while(fast) { fast = fast->next; if(!fast) return NULL; fast = fast->next; slow = slow->next; if(fast == slow)//find the cycle { slow = head; while(slow != fast) { fast = fast->next; slow = slow->next; } return fast; } } }};
Leetcode linked list Cycle & linked list cycle II