diff --git a/src/algorithms/linked-list/hare-tortoise-algorithm/README.md b/src/algorithms/linked-list/hare-tortoise-algorithm/README.md new file mode 100644 index 00000000..735493a3 --- /dev/null +++ b/src/algorithms/linked-list/hare-tortoise-algorithm/README.md @@ -0,0 +1,3 @@ +# Floyd's Cycle Detection Algorithm (aka Hare and Tortoise Algorithm) +Floyd algorithm for finding the cycles in a linked list is used to determine presence of a cycle in the linked list using constant space and linear time (i.e. space complexity = O(1) and time comoplexity = O(n), where n is number of nodes in the list). + The algorithm uses two pointers where one pointer moves a littile faster (the hare pointer). If at any point of traversal, the fast pointer meets the slow pointer, we can say that we have a cycle in the linked list. Conversly if the fast pointer hits a null, we have reached the end of list and no cycle is present. diff --git a/src/algorithms/linked-list/hare-tortoise-algorithm/__test__/hareTortoise.test.js b/src/algorithms/linked-list/hare-tortoise-algorithm/__test__/hareTortoise.test.js new file mode 100644 index 00000000..c566ae7d --- /dev/null +++ b/src/algorithms/linked-list/hare-tortoise-algorithm/__test__/hareTortoise.test.js @@ -0,0 +1,36 @@ +import LinkedList from "../../../../data-structures/linked-list/LinkedList"; +import LinkedListNode from "../../../../data-structures/linked-list/LinkedListNode"; +import hareAndTortoise from "../hareTortoise"; + +function getTail(linkedList){ + let tail = linkedList.head; + while(tail.next){ + tail=tail.next; + } + return tail; +} +describe('cycleDetection',()=>{ + it('should be able to properly detect no cycles in a linked list',()=>{ + let simpleLinkedList = new LinkedList(); + simpleLinkedList + .append(1) + .append(2) + .append(3); + + const containsCycle = hareAndTortoise(simpleLinkedList); + expect(containsCycle).toEqual(false); + }); + it('should detect a cycle in the linked list',()=>{ + let cyclicLinkedList = new LinkedList(); + cyclicLinkedList + .append(1) + .append(2) + .append(3) + .append(4); + const tail = getTail(cyclicLinkedList); + tail.next = cyclicLinkedList.head; + const containsCycle = hareAndTortoise(cyclicLinkedList); + expect(containsCycle).toEqual(true); + }); + +}) diff --git a/src/algorithms/linked-list/hare-tortoise-algorithm/hareTortoise.js b/src/algorithms/linked-list/hare-tortoise-algorithm/hareTortoise.js new file mode 100644 index 00000000..6b9d8b33 --- /dev/null +++ b/src/algorithms/linked-list/hare-tortoise-algorithm/hareTortoise.js @@ -0,0 +1,21 @@ +/** + * @param {LinkedList} linkedList + * @returns {boolean} + */ + +export default function hareAndTortoise(linkedList){ + let hare = linkedList.head; + let tortoise = linkedList.head; + while(hare && hare.next && hare.next.next){ + hare = hare.next.next; + tortoise = tortoise.next; + //iterate till "hare" has not reached the end of list + if(hare == tortoise){ + // we got a cycle + return true; + } + + } + // no cycle just the end of list + return false; +} \ No newline at end of file