📖 Scenario: Imagine you are building a task scheduler that runs tasks in order. Each task can depend on other tasks. To make sure the scheduler works correctly, you need to check if there is a cycle in the task dependencies. A cycle means some tasks depend on each other in a loop, which makes scheduling impossible.
🎯 Goal: You will create a program that detects if there is a cycle in a directed graph representing task dependencies. The graph is given as an adjacency list. You will use depth-first search (DFS) with recursion to find cycles.
📋 What You'll Learn
Create a directed graph as an adjacency list using a TypeScript object.
Create a helper array to track visited nodes and recursion stack.
Implement a recursive function to detect cycles using DFS.
Print whether the graph contains a cycle or not.
💡 Why This Matters
🌍 Real World
Cycle detection is important in task scheduling, detecting deadlocks, and verifying dependencies in software projects.
💼 Career
Understanding cycle detection helps in roles like software developer, system engineer, and data scientist where graph algorithms are used.
Progress0 / 4 steps
1
Create the directed graph as an adjacency list
Create a variable called graph as an object with these exact entries: 0: [1], 1: [2], 2: [0, 3], 3: [4], 4: []
DSA Typescript
Hint
Use a TypeScript object where keys are numbers and values are arrays of numbers representing edges.
2
Create visited and recursion stack arrays
Create two boolean arrays called visited and recStack with length 5, initialized with false values
DSA Typescript
Hint
Use new Array(5).fill(false) to create arrays of booleans.
3
Implement the recursive DFS function to detect cycles
Write a function called isCyclicUtil that takes a node number and returns a boolean. It should mark visited[node] and recStack[node] as true. Then for each neighbor in graph[node], if the neighbor is not visited, recursively call isCyclicUtil(neighbor) and return true if it returns true. If the neighbor is in recStack, return true. After checking neighbors, set recStack[node] to false and return false.
DSA Typescript
Hint
Use recursion and check neighbors carefully. Remember to update recStack when entering and leaving nodes.
4
Check all nodes and print if the graph has a cycle
Write a loop from 0 to 4 using i. For each i, if visited[i] is false, call isCyclicUtil(i). If it returns true, print "Graph contains a cycle" and return. After the loop, print "Graph does not contain a cycle".
DSA Typescript
Hint
Loop through all nodes and call isCyclicUtil. Print the result based on the return value.
Practice
(1/5)
1. What does cycle detection in a directed graph help us find?
easy
A. Whether there is a path that starts and ends at the same node following edge directions
B. The shortest path between two nodes
C. The total number of nodes in the graph
D. The maximum degree of any node
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 A
Quick Check:
Cycle detection = finding directed loops [OK]
Hint: Cycle means path loops back following edge directions [OK]
Common Mistakes:
Confusing cycle with shortest path
Ignoring edge directions
Thinking cycle means any repeated node without direction
2. Which TypeScript data structure is commonly used to track nodes currently in recursion stack during cycle detection?
easy
A. Queue
B. Array
C. Map
D. Set
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 D
Quick Check:
Recursion stack tracking uses Set [OK]
Hint: Use Set for fast membership check in recursion stack [OK]
Common Mistakes:
Using Array and checking membership with loops (slow)
Using Queue which is FIFO, not suitable here
Using Map without key-value need
3. What will be the output of the following TypeScript code snippet detecting cycle in a directed graph?
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()));
medium
A. false
B. undefined
C. true
D. Error
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 C
Quick Check:
Cycle exists in 1->2->3->1 path [OK]
Hint: Cycle if recursion stack revisits a node [OK]
Common Mistakes:
Ignoring recursion stack check
Assuming no cycle if visited is true
Confusing visited and recursion stack sets
4. Identify the bug in this TypeScript cycle detection function for a directed graph:
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;
}
medium
A. Missing check if neighbor is in recursion stack to detect cycle
B. Visited set is not updated correctly
C. recStack is never cleared
D. Function does not return boolean
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 A
Quick Check:
Check recStack for back edges to detect cycles [OK]
Hint: Always check recursion stack for back edges [OK]
Common Mistakes:
Skipping recursion stack membership check
Confusing visited and recursion stack roles
Not removing node from recursion stack after recursion
5. Given a directed graph represented as adjacency list: