PracticeNeetCode ↗LeetCode ↗
There are numCourses courses labeled 0 to numCourses - 1. Given prerequisite pairs [a, b] meaning a requires b first, return whether it's possible to finish every course.
visiting set (nodes on the current DFS path) and a visited set (nodes already confirmed safe).visiting, return False (cycle). If it's in visited, return True. Otherwise mark it visiting, recurse into every prerequisite, then move it from visiting to visited and return True.False the moment any call reports a cycle, otherwise return True.Time: O(V + E) — Space: O(V + E)
def canFinish(numCourses: int, prerequisites: list[list[int]]) -> bool:
graph = {i: [] for i in range(numCourses)}
for course, pre in prerequisites:
graph[course].append(pre)
visiting, visited = set(), set()
def dfs(course: int) -> bool:
if course in visiting:
return False
if course in visited:
return True
visiting.add(course)
for pre in graph[course]:
if not dfs(pre):
return False
visiting.remove(course)
visited.add(course)
return True
return all(dfs(course) for course in range(numCourses))How the solution above works, piece by piece.
graph[course] = list of its prerequisites.visiting holds courses on the current DFS path; visited holds courses already proven completable.visiting means a cycle → False. A course already in visited is fine → True without re-checking.all(dfs(course) ...) checks every course (the graph may be disconnected). O(V + E).Running it on numCourses = 2, prerequisites = [[1, 0], [0, 1]]: