Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Course Schedule in Python
The Course Schedule problem asks whether we can complete all courses given their prerequisites. This is essentially a cycle detection problem in a directed graph where courses are nodes and prerequisites are edges.
Problem Understanding
Given a number of courses and prerequisite pairs, we need to determine if it's possible to finish all courses. For example, if we have 2 courses and prerequisites = [[1, 0]], it means to take course 1, we must first complete course 0. This is possible, so we return True.
Algorithm Approach
We solve this using Depth-First Search (DFS) with cycle detection ?
- Build an adjacency list from prerequisites
- Use a visited array with three states: 0 (unvisited), -1 (visiting), 1 (visited)
- If we encounter a node with state -1 during DFS, we found a cycle
- If no cycles exist, all courses can be completed
Implementation
class Solution:
def canFinish(self, numCourses, prerequisites):
if len(prerequisites) == 0:
return True
visited = [0 for i in range(numCourses)]
adj_list = self.make_graph(prerequisites)
for i in range(numCourses):
if not visited[i]:
if not self.cycle(adj_list, visited, i):
return False
return True
def cycle(self, adj_list, visited, current_node=0):
if visited[current_node] == -1: # Currently visiting - cycle found
return False
if visited[current_node] == 1: # Already visited
return True
visited[current_node] = -1 # Mark as visiting
if current_node in adj_list:
for neighbor in adj_list[current_node]:
if not self.cycle(adj_list, visited, neighbor):
return False
visited[current_node] = 1 # Mark as visited
return True
def make_graph(self, prerequisites):
adj_list = {}
for course, prereq in prerequisites:
if prereq in adj_list:
adj_list[prereq].append(course)
else:
adj_list[prereq] = [course]
return adj_list
# Test the solution
solution = Solution()
print(solution.canFinish(2, [[1, 0]]))
print(solution.canFinish(2, [[1, 0], [0, 1]]))
True False
How It Works
The algorithm uses three states for each node ?
- 0 (White): Unvisited node
- -1 (Gray): Currently being processed (visiting)
- 1 (Black): Completely processed (visited)
When we encounter a gray node during DFS traversal, it indicates a back edge, which means a cycle exists in the graph.
Example Walkthrough
For prerequisites = [[1, 0], [0, 1]] ?
- Build graph: {0: [1], 1: [0]}
- Start DFS from node 0, mark it as gray (-1)
- Visit neighbor 1, mark it as gray (-1)
- From node 1, try to visit neighbor 0
- Node 0 is already gray, so cycle detected
- Return False
Time and Space Complexity
- Time Complexity: O(V + E) where V is number of courses and E is number of prerequisites
- Space Complexity: O(V + E) for the adjacency list and visited array
Conclusion
The course schedule problem is solved using DFS-based cycle detection. If the prerequisite graph contains a cycle, it's impossible to complete all courses. Otherwise, all courses can be finished.
