Course Schedule — Topological Sort with Cycle Detection
Use Kahn’s algorithm (BFS) or DFS to detect cycles in the prerequisite graph and decide feasibility.
Problem Statement
Given the number of courses and prerequisite pairs, determine if all courses can be completed.
Why This Problem Matters
- Classic application of topological sorting and cycle detection.
- Reinforces understanding of in-degree counts and graph traversal.
- Serves as the basis for scheduling and dependency resolution problems.
Thought Process
Model as directed graph
Edge from prerequisite to course; cycle implies impossible completion.
Apply topological sort
Kahn’s algorithm removes nodes with in-degree zero, simulating course completion.
Check processed count
If all courses processed, schedule feasible; otherwise a cycle exists.
Step-by-Step Reasoning
- Build adjacency list and in-degree array.
- Seed queue with all nodes having in-degree zero.
- Pop queue, decrement in-degree of neighbors; enqueue when they reach zero.
- Return true if processed count equals numCourses.
Dry Run
numCourses = 2, prerequisites = [[1,0]]
Order 0→1 processed; feasible.
prerequisites = [[1,0],[0,1]]
Queue empties early; processed < numCourses → cycle detected.
Complexity Analysis
Time
O(V + E)
Space
O(V + E)
Why
Graph traversal visits each node and edge once.
Annotated Solution
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
public class CourseSchedule {
public boolean canFinish(int numCourses, int[][] prerequisites) {
List<List<Integer>> graph = new ArrayList<>();
for (int i = 0; i < numCourses; i += 1) {
graph.add(new ArrayList<>());
}
int[] indegree = new int[numCourses];
for (int[] edge : prerequisites) {
int course = edge[0];
int prereq = edge[1];
graph.get(prereq).add(course);
indegree[course] += 1;
}
ArrayDeque<Integer> queue = new ArrayDeque<>();
for (int i = 0; i < numCourses; i += 1) {
if (indegree[i] == 0) {
queue.addLast(i);
}
}
int processed = 0;
while (!queue.isEmpty()) {
int node = queue.removeFirst();
processed += 1;
for (int neighbor : graph.get(node)) {
indegree[neighbor] -= 1;
if (indegree[neighbor] == 0) {
queue.addLast(neighbor);
}
}
}
return processed == numCourses;
}
}Kahn’s algorithm systematically removes nodes without prerequisites, revealing cycles when nodes remain with non-zero in-degree.
Common Pitfalls
- Building edges in wrong direction prevents correct in-degree computations.
- Forgetting to increment processed count or to check equality leads to false positives.
- DFS alternatives require three-color marking; ignoring state leads to infinite recursion.
Follow-Up Questions
- How would you output a valid order if it exists? (Return the topological order.)
- Can you detect which courses are part of the cycle?