Problem Statement
Course Schedule
You have a list of courses to take, numbered from 0 up to numCourses - 1. Some courses have to be taken in order. You are given a list called prerequisites, where each entry prerequisites[i] = [ai, bi] means "you must take course bi before you can take course ai." The question is simple: can you finish every single course? Return true if there is some order that lets you take all of them, and false if there is no possible order.
Signals to notice
Brute force first
Try all possible orderings — factorial time. That instinct is useful because it follows the prompt literally, but it usually keeps revisiting work the problem is begging you to organize.
The key insight
Topological sort with BFS (Kahn's) or DFS cycle detection. Once you hold onto the right piece of information from moment to moment, the problem feels less like trial and error and more like following a shape that was there all along.
Trace it on numCourses=2, prerequisites=[[1,0],[0,1]]
build graph: [1,0] -> adj[0]=[1], inDegree[1]=1; [0,1] -> adj[1]=[0], inDegree[0]=1 inDegree=[1,1]: scan courses 0..1, none have inDegree 0 -> queue=[] count=0; while-loop never runs because queue is empty no course ever reaches inDegree 0 (cycle 0<->1) -> count stays 0 return count==numCourses -> 0==2 -> false
What must stay true
A valid ordering exists if and only if the dependency graph has no cycles. When you keep that truth intact, each local choice supports the larger solution instead of fighting it.
Shape of the loop
build adj list + inDegree from prerequisites (edge prereq -> course) queue <- all courses with inDegree == 0; count <- 0 while queue not empty: course <- queue.pop(); count++ for next in adj[course]: inDegree[next]--; if 0 -> queue.push(next) return count == numCourses
Pseudocode only — the full worked solution lives in the Solution tab.
Easy way to go wrong
Not detecting cycles — if you can't process all courses, there's a cycle. The fix is usually to return to the meaning of each move, not just the steps themselves.