What if your to-do list secretly traps you in an endless loop? Discover how to find and fix it!
Why Cycle Detection in Directed Graph in DSA Typescript?
Imagine you are managing tasks where some tasks depend on others to be done first. You try to check manually if any task depends on itself through a chain of dependencies. This is like trying to find if a circle exists in your to-do list.
Manually checking each task and its dependencies is slow and confusing. You might miss a hidden loop where a task indirectly depends on itself. This causes delays and errors because you can't start tasks that are stuck in a cycle.
Cycle detection in directed graphs helps automatically find these loops. It uses a smart way to track which tasks are being checked and which are already done, so it quickly spots if a cycle exists without checking everything repeatedly.
function hasCycle(tasks) {
for (let task of tasks) {
if (task.dependsOn(task)) return true;
}
return false;
}function detectCycle(graph) {
const visited = new Set();
const stack = new Set();
function dfs(node) {
if (stack.has(node)) return true;
if (visited.has(node)) return false;
stack.add(node);
visited.add(node);
for (const neighbor of graph[node]) {
if (dfs(neighbor)) return true;
}
stack.delete(node);
return false;
}
for (const node in graph) {
if (dfs(node)) return true;
}
return false;
}This concept enables you to automatically detect impossible task orders or infinite loops in workflows, making your systems reliable and efficient.
In software build systems, cycle detection ensures that modules do not depend on each other in a loop, preventing endless build failures.
Manual checking for cycles is slow and error-prone.
Cycle detection uses tracking sets to find loops efficiently.
It helps ensure tasks or processes can be completed without infinite waiting.
Practice
Solution
Step 1: Understand cycle in directed graph
A cycle means a path that starts and ends at the same node following the direction of edges.Step 2: Identify what cycle detection finds
Cycle detection checks if such a path exists in the graph.Final Answer:
Whether there is a path that starts and ends at the same node following edge directions -> Option AQuick Check:
Cycle detection = finding directed loops [OK]
- Confusing cycle with shortest path
- Ignoring edge directions
- Thinking cycle means any repeated node without direction
Solution
Step 1: Identify recursion stack tracking
We need to quickly check if a node is in the current recursion path.Step 2: Choose data structure for fast membership check
A Set allows O(1) membership check, ideal for tracking nodes in recursion stack.Final Answer:
Set -> Option DQuick Check:
Recursion stack tracking uses Set [OK]
- Using Array and checking membership with loops (slow)
- Using Queue which is FIFO, not suitable here
- Using Map without key-value need
const graph = new Map([
[1, [2]],
[2, [3]],
[3, [1]]
]);
function hasCycle(node: number, visited: Set<number>, recStack: Set<number>): boolean {
if (!visited.has(node)) {
visited.add(node);
recStack.add(node);
for (const neighbor of graph.get(node) || []) {
if (!visited.has(neighbor) && hasCycle(neighbor, visited, recStack)) {
return true;
} else if (recStack.has(neighbor)) {
return true;
}
}
}
recStack.delete(node);
return false;
}
console.log(hasCycle(1, new Set(), new Set()));Solution
Step 1: Analyze graph edges
Graph edges: 1->2, 2->3, 3->1 form a cycle.Step 2: Trace recursion and cycle detection
Starting at 1, recursion visits 2, then 3, then back to 1 which is in recursion stack, so returns true.Final Answer:
true -> Option CQuick Check:
Cycle exists in 1->2->3->1 path [OK]
- Ignoring recursion stack check
- Assuming no cycle if visited is true
- Confusing visited and recursion stack sets
function detectCycle(node: number, visited: Set<number>, recStack: Set<number>): boolean {
if (visited.has(node)) {
return false;
}
visited.add(node);
recStack.add(node);
for (const neighbor of graph.get(node) || []) {
if (detectCycle(neighbor, visited, recStack)) {
return true;
}
}
recStack.delete(node);
return false;
}Solution
Step 1: Review cycle detection logic
Cycle detection requires checking if neighbor is already in recursion stack to detect back edge.Step 2: Identify missing condition
The code calls recursion but does not check if neighbor is in recStack, so misses cycles.Final Answer:
Missing check if neighbor is in recursion stack to detect cycle -> Option AQuick Check:
Check recStack for back edges to detect cycles [OK]
- Skipping recursion stack membership check
- Confusing visited and recursion stack roles
- Not removing node from recursion stack after recursion
const graph = new Map([ [1, [2, 3]], [2, [4]], [3, [4, 5]], [4, [6]], [5, [3]], [6, []] ]);Which nodes are part of at least one cycle?
Solution
Step 1: Analyze edges for cycles
Edges: 3->5 and 5->3 form a cycle between nodes 3 and 5.Step 2: Check other nodes
Nodes 1, 2, 4, 6 do not form cycles as no back edges lead to them.Final Answer:
[3, 5] -> Option BQuick Check:
Cycle nodes = 3 and 5 only [OK]
- Including nodes not in any cycle
- Missing nodes that form cycles
- Confusing path with cycle
Ready to prove it?
Pass the test and this pattern moves unknown
