Course Schedule
Take the courses in waves. A course with no unfinished prerequisites is always safe to take now. Taking it removes one arrow from every course that waited on it. If the queue runs dry before all n courses are taken, the courses left over are all waiting on each other, so there is a loop.
A course is safe to take exactly when its waiting count is 0: every prerequisite is already taken, so nothing blocks it.
Problem
There are numCourses courses, labelled from 0 to numCourses − 1. prerequisites[i] = [a, b] means you must finish course b before you can take course a.
Return true if you can take every course. Return false if some courses block each other, so that none of them can be taken first.
numCourses, and prerequisites, a list of pairs [a, b].
true if every course can be taken in some order, otherwise false.
Take course 0 first, then course 1. Nothing blocks anything.
Course 1 needs course 0, and course 0 needs course 1. Neither one can be taken first, so the schedule is impossible.
- • 1 ≤ numCourses ≤ 2000
- • 0 ≤ prerequisites.length ≤ 5000
- • Each prerequisites[i] has exactly 2 numbers.
- • 0 ≤ aᵢ, bᵢ < numCourses
- • All the pairs in prerequisites are different.
First, think yourself
Before opening any solution, try to answer these on paper. Use hints only when stuck — each hint is counted.
- 1.
For a pair [a, b], which course has to come first: a or b? Which way should the arrow point?
- 2.
If a group of courses all need each other, can any one of them be taken first?
- 3.
Which courses have no prerequisites at all? Could I start there?
- 4.
After I take a course, which other courses get closer to being free?
- 5.
If I manage to take every course one at a time, how many courses should I have taken at the end?
Brute force approach
Optimized approach
Why does this algorithm work?
Dry run
All approaches compared
| Approach | Idea | Time | Space |
|---|---|---|---|
| Brute Force | From each course, follow the prerequisite arrows; if the walk returns to the start, it is stuck in a loop | O(V · (V + E)) | O(V + E) |
| Optimal | Keep a count of unfinished prerequisites; take free courses from a queue; if every course gets taken, there is no loop | O(V + E) | O(V + E) |
Why does this belong to this pattern?
- “prerequisites [a, b]”Each pair is an arrow: course b must come before course a. The courses form a directed graph.
- “can you finish all courses?”A yes or no question. It asks whether a loop exists, not for the order itself.
- “courses that block each other”That is a loop. A loop means the processing order can never start.
This is the anchor question of the cycle-detection sub-pattern. The sort is a tool here. If every course can be taken, a topological order exists, so there is no loop. If the queue runs dry early, the courses left over form a loop. Only the number of taken courses matters. The next two questions need different output: the cycle itself (GFG) and the safe nodes (LC 802).
Don't make this mistake
This is the undirected trick: remember everything seen and treat a revisit as a loop. On the dry-run courses (0 → 1, 0 → 2, 1 → 3, 2 → 3, 3 → 4), the walk goes 0 → 1 → 3 → 4 and finishes 3. Back at 0, it tries 0 → 2 → 3. Course 3 is already visited, so the wrong code says loop. But course 3 is finished, not on the current path. The real answer is true, and this code says false.
The count belongs to the course that has to wait, which is a (the first number). On the dry run the wrong count gives waiting = [2, 1, 1, 1, 0] instead of [0, 1, 1, 2, 1]. Only course 4 looks free, so the queue takes 4, nothing unlocks, and the code says false. The real answer is true.
When the loop ends, the queue is always empty, so this test always passes, even when courses are stuck. On example 2, [[1, 0], [0, 1]], no course is free at the start, the queue is empty at once, and the code says true. Count the courses you took instead.
Want to implement this?
Write it yourself on LeetCode, then come back and compare your code with the solutions above.
Open coding workspaceHow this concept connects to System Design & C++ Systems
Top engineering interviews test whether you understand how algorithms like Topological Sort translate into production architectures and low-level memory mechanics.