Skip to content

Commit

Permalink
Merge pull request cp-algorithms#1142 from sourav15102/master
Browse files Browse the repository at this point in the history
Added Hare n Tortoise algorithm
  • Loading branch information
jakobkogler authored Sep 10, 2023
2 parents f7ab1da + eb09530 commit f38883c
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Compiled pages are published at [https://cp-algorithms.com/](https://cp-algorith

### New articles

- (10 September 2023) [Tortoise and Hare Algorithm](https://cp-algorithms.com/others/tortoise_and_hare.html)
- (12 July 2023) [Finding faces of a planar graph](https://cp-algorithms.com/geometry/planar.html)
- (18 April 2023) [Bit manipulation](https://cp-algorithms.com/algebra/bit-manipulation.html)
- (17 October 2022) [Binary Search](https://cp-algorithms.com/num_methods/binary_search.html)
Expand Down
2 changes: 1 addition & 1 deletion src/algebra/factorization.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ In each iteration the first pointer advances to the next element, but the second
It's not hard to see, that if there exists a cycle, the second pointer will make at least one full cycle and then meet the first pointer during the next few cycle loops.
If the cycle length is $\lambda$ and the $\mu$ is the first index at which the cycle starts, then the algorithm will run in $O(\lambda + \mu)$ time.

This algorithm is also known as **tortoise and the hare algorithm**, based on the tale in which a tortoise (here a slow pointer) and a hare (here a faster pointer) make a race.
This algorithm is also known as the [Tortoise and Hare algorithm](../others/tortoise_and_hare.md), based on the tale in which a tortoise (here a slow pointer) and a hare (here a faster pointer) make a race.

It is actually possible to determine the parameter $\lambda$ and $\mu$ using this algorithm (also in $O(\lambda + \mu)$ time and $O(1)$ space), but here is just the simplified version for finding the cycle at all.
The algorithm and returns true as soon as it detects a cycle.
Expand Down
1 change: 1 addition & 0 deletions src/navigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ search:
- [Scheduling jobs on two machines](schedules/schedule_two_machines.md)
- [Optimal schedule of jobs given their deadlines and durations](schedules/schedule-with-completion-duration.md)
- Miscellaneous
- [Tortoise and Hare Algorithm (Linked List cycle detection)](others/tortoise_and_hare.md)
- [Josephus problem](others/josephus_problem.md)
- [15 Puzzle Game: Existence Of The Solution](others/15-puzzle.md)
- [The Stern-Brocot Tree and Farey Sequences](others/stern_brocot_tree_farey_sequences.md)
114 changes: 114 additions & 0 deletions src/others/tortoise_and_hare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
tags:
- Original
---

# Floyd's Linked List Cycle Finding Algorithm

Given a linked list where the starting point of that linked list is denoted by **head**, and there may or may not be a cycle present. For instance:

<center>!["Linked list with cycle"](tortoise_hare_algo.png)</center>

Here we need to find out the point **C**, i.e the starting point of the cycle.

## Proposed algorithm
The algorithm is called **Floyd’s Cycle Algorithm or Tortoise And Hare algorithm**.
In order to figure out the starting point of the cycle, we need to figure out of the the cycle even exists or not.
So, it involved two steps:
1. Figure out the presence of the cycle.
2. Find out the starting point of the cycle.

### Step 1: Presence of the cycle
1. Take two pointers $slow$ and $fast$.
2. Both of them will point to head of the linked list initially.
3. $slow$ will move one step at a time.
4. $fast$ will move two steps at a time. (twice as speed as $slow$ pointer).
5. Check if at any point they point to the same node before any one(or both) reach null.
6. If they point to any same node at any point of their journey, it would indicate that the cycle indeed exists in the linked list.
7. If we get null, it would indicate that the linked list has no cycle.

<center>!["Found cycle"](tortoise_hare_cycle_found.png)</center>

Now, that we have figured out that there is a cycle present in the linked list, for the next step we need to find out the starting point of cycle, i.e., **C**.
### Step 2: Starting point of the cycle
1. Reset the $slow$ pointer to the **head** of the linked list.
2. Move both pointers one step at a time.
3. The point they will meet at will be the starting point of the cycle.

```java
// Presence of cycle
public boolean hasCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;

while(slow !=null && fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
if(slow==fast){
return true;
}
}

return false;
}
```

```java
// Assuming there is a cycle present and slow and fast are point to their meeting point
slow = head;
while(slow!=fast){
slow = slow.next;
fast = fast.next;
}

return slow; // the starting point of the cycle.
```

## Why does it work

### Step 1: Presence of the cycle
Since the pointer $fast$ is moving with twice as speed as $slow$, we can say that at any point of time, $fast$ would have covered twice as much distance as $slow$.
We can also deduce that the difference between the distance covered by both of these pointers is increasing by $1$.
```
slow: 0 --> 1 --> 2 --> 3 --> 4 (distance covered)
fast: 0 --> 2 --> 4 --> 6 --> 8 (distance covered)
diff: 0 --> 1 --> 2 --> 3 --> 4 (difference between distance covered by both pointers)
```
Let $L$ denote the length of the cycle, and $a$ represent the number of steps required for the slow pointer to reach the entry of cycle. There exists a positive integer $k$ ($k > 0$) such that $k \cdot L \geq a$.
When the slow pointer has moved $k \cdot L$ steps, and the fast pointer has covered $2 \cdot k \cdot L$ steps, both pointers find themselves within the cycle. At this point, there is a separation of $k \cdot L$ between them. Given that the cycle's length remains $L$, this signifies that they meet at the same point within the cycle, resulting in their encounter.

### Step 2: Starting point of the cycle

Lets try to calculate the distance covered by both of the pointers till they point they met within the cycle.

<center>!["Proof"](tortoise_hare_proof.png)</center>

$slowDist = a + xL + b$ $x\ge0$

$fastDist = a + yL + b$ $y\ge0$

- $slowDist$ is the total distance covered by slow pointer.
- $fastDist$ is the total distance covered by fast pointer.
- $a$ is the number of steps both pointers need to take to enter the cycle.
- $b$ is the distance between **C** and **G**, i.e., distance between the starting point of cycle and meeting point of both pointers.
- $x$ is the number of times the slow pointer has looped inside the cycle, starting from and ending at **C**.
- $y$ is the number of times the fast pointer has looped inside the cycle, starting from and ending at **C**.

$slowDist = 2 \cdot (fastDist)$

$a + yL + b = 2(a + xL + b)$

Resolving the formula we get:

$a=(y-2x)L-b$

where $y-2x$ is an integer

This basically means that $a$ steps is same as doing some number of full loops in cycle and go $b$ steps backwards.
Since the fast pointer already is $b$ steps ahead of the entry of cycle, if fast pointer moves another $a$ steps it will end up at the entry of the cycle.
And since we let the slow pointer start at the start of the linked list, after $a$ steps it will also end up at the cycle entry. So, if they both move $a$ step they both will meet the entry of cycle.

# Problems:
- [Linked List Cycle (EASY)](https://leetcode.com/problems/linked-list-cycle/)
- [Find the Duplicate Number (Medium)](https://leetcode.com/problems/find-the-duplicate-number/)

Binary file added src/others/tortoise_hare_algo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/others/tortoise_hare_cycle_found.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/others/tortoise_hare_proof.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit f38883c

Please sign in to comment.