Skip to content

Commit 3588b35

Browse files
authored
feat: Add Floyd cycle-finding algorithm. (#9)
1 parent 76bcf08 commit 3588b35

File tree

5 files changed

+81
-0
lines changed

5 files changed

+81
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ So far, the following exercises have been covered:
88

99
- [Autocomplete](./autocomplete/) – implements an autocomplete feature using a trie
1010
- [Continous maximum](./continuousmax/) – calculates the maximum of a sliding window
11+
- [Floyd](./floyd/) – implements Floyd's cycle-finding "Tortoise and Hare" algorithm
1112
- [Heap](./heap/) – implements a heap from scratch, without using the built-in `container/heap` package
1213
- [Radix sort](./radixsort/) – implements radix sort
1314
- [Remove k-th last element](./removekthlastelement/) – removes the k-th last element from a single-linked list

floyd/documentation.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Package floyd implements Floyd's cycle-finding "Tortoise and Hare"
2+
// algorithm.
3+
package floyd

floyd/has_cycle.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package floyd
2+
3+
func HasCycle(head *Node) bool {
4+
if head == nil {
5+
return false
6+
}
7+
8+
tortoise, hare := head, head
9+
for hare != nil && hare.Next != nil {
10+
tortoise = tortoise.Next
11+
hare = hare.Next.Next
12+
13+
if tortoise == hare {
14+
return true
15+
}
16+
}
17+
18+
return false
19+
}

floyd/has_cycle_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package floyd_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
"github.com/thenativeweb/codingcircle/floyd"
8+
)
9+
10+
func TestHasCycle(t *testing.T) {
11+
t.Run("returns false for an empty list", func(t *testing.T) {
12+
assert.False(t, floyd.HasCycle(nil))
13+
})
14+
15+
t.Run("returns false for a single node", func(t *testing.T) {
16+
list := floyd.NewList(2)
17+
18+
assert.False(t, floyd.HasCycle(list))
19+
})
20+
21+
t.Run("returns false for a list without a cycle", func(t *testing.T) {
22+
list := floyd.NewList(2, 3, 5, 7, 11)
23+
24+
assert.False(t, floyd.HasCycle(list))
25+
})
26+
27+
t.Run("returns true for a list with a cycle", func(t *testing.T) {
28+
list := floyd.NewList(2, 3, 5, 7, 11)
29+
30+
last := list.Next.Next.Next.Next
31+
third := list.Next.Next
32+
last.Next = third
33+
34+
assert.True(t, floyd.HasCycle(list))
35+
})
36+
}

floyd/node.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package floyd
2+
3+
type Node struct {
4+
Value int
5+
Next *Node
6+
}
7+
8+
func NewList(values ...int) *Node {
9+
if len(values) == 0 {
10+
return nil
11+
}
12+
13+
head := &Node{values[0], nil}
14+
current := head
15+
16+
for _, value := range values[1:] {
17+
current.Next = &Node{value, nil}
18+
current = current.Next
19+
}
20+
21+
return head
22+
}

0 commit comments

Comments
 (0)