You're given a set of courses, labeled from 0 to numCourses - 1, and a list of prerequisite pairs. Each pair [a, b] means course a requires course b to be completed first. Your task is to determine if it's possible to finish all the courses. This boils down to detecting whether the prerequisite structure contains any cycles — if it does, completing all courses is impossible.
We can model this as a directed graph:
The goal is to perform a depth-first traversal (DFS) on each node and detect cycles. To do this, we use a state tracking array for all nodes:
0
= UNVISITED: the course has not been checked yet.1
= VISITING: we're currently exploring this course’s prerequisites.2
= VISITED: the course and all its descendants have been verified and no cycle was found.
1. Build the graph: Use an adjacency list to represent which courses depend on which prerequisites.
2. Initialize visit state: Create a state array of size numCourses initialized to 0 (UNVISITED).
3. Define DFS: For each course, recursively traverse its prerequisites.
4. Run DFS: Loop through all courses. For each UNVISITED course, call DFS. If any DFS call detects a cycle, return False.
5. If no cycles are found: Return True after checking all courses.
Time Complexity: O(V + E), where V is the number of courses and E is the number of prerequisites. Each node and edge is visited once.
Space Complexity: O(V + E), to store the graph and the visit state.
The key idea is that a valid course schedule corresponds to a Directed Acyclic Graph (DAG). If you can show there is no cycle in the graph formed by prerequisites, then there's some order in which all courses can be taken.
This is a classic graph cycle detection problem disguised in the context of course scheduling. By translating prerequisites into edges and using DFS with a visited state tracker, we can efficiently determine whether a valid schedule exists.