Linked list cycle II

problem [https://leetcode.com/problems/linked-list-cycle-ii/ 142. Linked List Cycle II]

Problem description
Given a linked list, return the node where the cycle begins. If there is no cycle, return.

There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the  pointer. Internally,  is used to denote the index of the node that tail's   pointer is connected to. Note that  is not passed as a parameter.

Notice that you should 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.


 * Constraints
 * The number of the nodes in the list is in the range.
 * is  or a valid index in the linked-list.
 * is  or a valid index in the linked-list.


 * Follow up: Can you solve it using O(1) (i.e. constant) memory?

Analysis
One approach we can use to keep O(1) memory is to use the Floyd's loop detection algorithm.
 * 1) Check whether we do have a loop using the slow-fast pointers method in the Linked list cycle problem.
 * 2) * If a loop is not found, then we do not need to go through further steps.
 * 3) If a loop is found, then we position the slow pointer back to the head of the loop, and keep the fast pointer where the two pointers have met up with each other.
 * 4) Move the slow pointer and the fast pointer one step each time.
 * 5) The node at which the two pointers meet again is the start of the loop.

Proof of correctness
Suppose that we have m steps from the head of the link list to the start of the loop, and n steps in the cycle.

First we use a slow pointer and a fast pointer to detect whether there is a loop. Stop the iteration when the two pointers meet up. (See Linked list cycle)
 * The slow pointer moves forward by 1 step per iteration.
 * The fast pointer moves forward by 2 steps per iteration.

If we have detected a cycle, one thing to note is that the slow pointer must have travelled less than the full cycle since its first entry into the loop.
 * This is because in the worst case, the fast pointer is just at the node in front of the slow pointer. The chasing distance is n-1. For the slow pointer, the number of steps from entering the loop from being caught up by the fast pointer &le; (n-1)/(2-1) = n-1. Then the slow pointer will be caught up by the fast pointer right before it reaches the start of the loop again.



Let x be the offset of the meeting point of the two pointers from the beginning of the cycle. x can be calculated as follows:
 * 1) Let k be the offset of the fast pointer from the beginning of the cycle. Since the fast pointer is m steps ahead of the slow pointer, we have k = m mod n. So k < n.
 * 2) Now the chasing distance for the fast pointer is n - k.
 * 3) Then x equals to the number of steps the slow pointer has traveled from entering the cycle to being caught by the fast pointer. Then x = (n - k) / (2 - 1) = n - k.

At this moment, it is also apparent that the distance from the meeting point to reaching the start of the cycle the next time (by going forward only) is n - x = n - (n - k) = k. In addition, we have k = m mod n. This means that from the meeting point, going k steps forward is equivalent to going m steps forward, which will both end up at the start of the cycle.

So the next steps will be:
 * 1) Put the slow pointer back to the head.
 * 2) Keep the fast pointer at the meeting point of both pointers.
 * 3) Move both the slow pointer and the fast pointer one step per iteration, until they meet up again.
 * 4) The new meeting point is the start of the cycle.

Time complexity
So the total time complexity is O(m + n), where m is the number of steps outside the loop, and n is the number of steps inside the loop. In other words, the time complexity is linearly related to the total number of nodes.
 * 1) In the first phase of detecting loop, sending the slow pointer from head to the meeting point takes m + (m mod n) < m + n steps.
 * 2) In the second phase of locating the start of the loop, sending the slow pointer from head to the start of loop takes m steps.

Space complexity
Since we only used the slow pointer and the fast pointer, without allocating extra objects, the space complexity is O(1).