Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Binary file modified .DS_Store
Binary file not shown.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
./node_modules
node_modules
File renamed without changes.
File renamed without changes.
File renamed without changes.
240 changes: 240 additions & 0 deletions Datastructure/Algorithms/Floyd_Cycle_Detection /index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
// Singly Linked List with optional circular mode (tail -> head)

class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}

class LinkedList {
constructor(value) {
this.head = new Node(value);
this.tail = this.head;
this.length = 1;
this.circular = false; // ring toggle
}

// ===== Ring controls =====
makeCircular() {
if (this.length > 0) {
this.tail.next = this.head;
this.circular = true;
}
return this;
}

breakCircular() {
if (this.circular && this.tail) {
this.tail.next = null;
this.circular = false;
}
return this;
}

// ===== Helpers =====
printList() {
const out = [];
let curr = this.head;
let seen = 0;
while (curr && seen < this.length) {
out.push(curr.value);
curr = curr.next;
seen++;
}
return out;
}

traverse(index) {
if (this.length === 0) return null;
if (index < 0) throw new Error("Negative index not supported");
let steps = this.circular ? (index % this.length) : index;
let curr = this.head;
while (steps-- > 0 && curr) curr = curr.next;
return curr;
}

// ===== Core ops =====
prepend(value) {
const newNode = new Node(value);
newNode.next = this.head;
this.head = newNode;
if (this.length === 0) this.tail = newNode;
if (this.circular && this.tail) this.tail.next = this.head;
this.length++;
return this;
}

append(value) {
const newNode = new Node(value);
if (this.length === 0) {
this.head = this.tail = newNode;
this.length = 1;
if (this.circular) this.tail.next = this.head;
return this;
}
if (this.circular) {
newNode.next = this.head; // ring must point back to head
this.tail.next = newNode;
this.tail = newNode;
} else {
this.tail.next = newNode;
this.tail = newNode;
}
this.length++;
return this;
}

insert(index, value) {
if (index <= 0) {
this.prepend(value);
return this.printList();
}
if (index >= this.length) {
this.append(value);
return this.printList();
}
const newNode = new Node(value);
const leader = this.traverse(index - 1);
newNode.next = leader.next;
leader.next = newNode;
if (leader === this.tail) this.tail = newNode;
this.length++;
return this.printList();
}

removeFirst() {
if (this.length === 0) return this;
if (this.length === 1) {
this.head = this.tail = null;
this.circular = false;
this.length = 0;
return this;
}
this.head = this.head.next;
if (this.circular && this.tail) this.tail.next = this.head;
this.length--;
return this;
}

removeLast() {
if (this.length === 0) return this;
if (this.length === 1) return this.removeFirst();

let prev = null;
let curr = this.head;

if (this.circular) {
while (curr.next !== this.head) {
prev = curr;
curr = curr.next;
}
// curr is tail
prev.next = this.head;
this.tail = prev;
} else {
while (curr.next && curr.next !== this.tail) {
curr = curr.next;
}
// curr is node before tail (or head if length==2)
prev = curr;
prev.next = null;
this.tail = prev;
}
this.length--;
return this;
}

remove(index) {
if (this.length === 0) return this.printList();
const norm = this.circular ? (index % this.length) : index;
if (norm < 0 || norm >= this.length) return this.printList();

if (norm === 0) {
this.removeFirst();
return this.printList();
}
if (norm === this.length - 1) {
this.removeLast();
return this.printList();
}

const leader = this.traverse(norm - 1);
const unwanted = leader.next;
leader.next = unwanted.next;
if (unwanted === this.tail) this.tail = leader;
if (this.circular && this.tail) this.tail.next = this.head;
this.length--;
return this.printList();
}

reverse() {
if (this.length <= 1) return this.printList();

const wasCircular = this.circular;
if (wasCircular) this.breakCircular();

let prev = null;
let curr = this.head;
this.tail = this.head;

while (curr) {
const next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
this.head = prev;

if (wasCircular) this.makeCircular();
return this.printList();
}

// Floyd's Tortoise & Hare
isCycle() {
let slow = this.head;
let first = this.head;
while(first && first.next) {
slow = slow.next;
first = first.next.next;

if(first == slow) return true;
}
return false;
}
}

// ===== Example usage =====
var myLinkedList = new LinkedList(10);
myLinkedList.append(5);
myLinkedList.append(52);
myLinkedList.prepend(9);
myLinkedList.insert(200, 99); // If index >= length, append
myLinkedList.insert(2, 19);
myLinkedList.insert(6, 19);

console.log("Linear list:", myLinkedList.printList()); // [9,10,19,5,52,99,19]
console.log("Is cycle:", myLinkedList.isCycle()); // false

// Make it circular
myLinkedList.makeCircular();
console.log("Made circular. Is cycle now?:", myLinkedList.isCycle()); // true
console.log("Safe print (length-limited):", myLinkedList.printList());

// Keep working while circular
myLinkedList.append(777);
console.log("After append (still circular):", myLinkedList.printList());

// Break the circle if you want linear-friendly ops / debugging
myLinkedList.breakCircular();
console.log("Broke circular. Is cycle?:", myLinkedList.isCycle()); // false

myLinkedList.remove(2);
myLinkedList.removeFirst();
myLinkedList.removeLast();

console.log("After removals:", myLinkedList.printList());
console.log("Reversed:", myLinkedList.reverse());
console.log("Final:", myLinkedList.printList());

// NOTE: Avoid JSON.stringify(list) while in circular mode (it will throw due to cyclic refs).
5 changes: 5 additions & 0 deletions Datastructure/Algorithms/Floyd_Cycle_Detection /readme.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Floyd Cycle Detection Algorithm

https://www.youtube.com/watch?v=uvkuqNwWiCQ

LeetCode - Linked List - https://leetcode.com/problems/linked-list-cycle/description/
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@

function merge(left, right) {
let arr = []
// let i = 0, j = 0;
// Break out of loop if any one of the array gets empty
while (left.length && right.length) {
// Pick the smaller among the smallest element of left and right sub arrays
if (left[0] < right[0]) {
arr.push(left.shift())
arr.push(left.shift()) // Here will be O(n) we can say - arr.push(left[i++]);
} else {
arr.push(right.shift())
arr.push(right.shift()) // Here will be O(n) we can say - arr.push(right[j++]);
}
}

Expand Down
File renamed without changes.
15 changes: 0 additions & 15 deletions Datastructure/BinaryHeap/index.js

This file was deleted.

Loading