Given numCourses and a list of prerequisite pairs, decide whether you can finish all courses — which is true exactly when the dependency graph contains no cycle. Kahn's BFS topological sort detects cycles in one pass by counting how many nodes it can fully process.
You have numCourses courses labelled 0 to numCourses - 1. Each pair [a, b] means “you must take b before a.” Can you complete all courses?
Example: numCourses = 4, prerequisites = [[1,0],[2,0],[3,1],[3,2]]. Taking 0, then 1 and 2 (order either way), then 3 works → true.
Cycle example: numCourses = 2, prerequisites = [[1,0],[0,1]]. You need 0 before 1 and 1 before 0 — impossible → false.
[a, b], add edge b → a (b unlocks a) and increment indegree[a].indegree === 0 have no prerequisites — they can be taken right now.finished, and for each neighbor decrement its indegree. If that neighbor's indegree hits 0, enqueue it.finished === numCourses → no cycle, true; otherwise a cycle trapped some courses.[a, b]means “b before a” — the directed edge goes from b to a, not a → b. Reversing this gives wrong indegrees and a broken sort.Both approaches are O(V + E) time and O(V + E)space. Kahn's is usually easier to implement iteratively (no recursion depth concern) and also gives you the actual topological order — useful in Course Schedule II.
0 has no prerequisites — enqueue them first.function canFinish(numCourses: number, prerequisites: number[][]): boolean {
// Build adjacency list and indegree counter
const adj: number[][] = Array.from({ length: numCourses }, () => []);
const indegree: number[] = new Array(numCourses).fill(0);
for (const [a, b] of prerequisites) {
adj[b].push(a); // b must be taken before a => edge b -> a
indegree[a]++;
}
// Seed the queue with all courses that have no prerequisites
const queue: number[] = [];
for (let i = 0; i < numCourses; i++) {
if (indegree[i] === 0) queue.push(i);
}
let finished = 0;
while (queue.length > 0) {
const cur = queue.shift()!;
finished++;
for (const neighbor of adj[cur]) {
indegree[neighbor]--;
if (indegree[neighbor] === 0) queue.push(neighbor);
}
}
// If every course was processed there is no cycle
return finished === numCourses;
}adj[b].push(a) records that finishing b unlocks a; indegree[a]++ counts how many prerequisites a still has. Edge direction is b → a because b must come first.indegree === 0have no outstanding prerequisites. They are the “roots” of the DAG and can be taken immediately.indegree[neighbor]simulates “this prerequisite is now satisfied.” When indegree reaches 0, the course is newly unlocked and joins the queue.finished < numCourses.O(V + E) time: every node is enqueued and dequeued at most once; every edge is visited exactly once when we walk adj[cur]. Space is also O(V + E) for the adjacency list and O(V) for indegrees and the queue.result.length === numCourses, else [].numCourses = 1 with no prerequisites is trivially true. An empty prerequisites list means all courses are independent and trivially orderable.| "can all tasks/courses be completed" with dependencies | Kahn's BFS topological sort + cycle check |
| directed dependency graph, detect cycle | BFS indegree drain OR 3-color DFS |
| "return a valid ordering" of tasks with prerequisites | Kahn's BFS — collect dequeued order |
| "no cycle" / "acyclic" / "DAG" in disguise | finished === numNodes check after topo-sort |
const adj: number[][] = Array.from({ length: n }, () => []);
const indegree: number[] = new Array(n).fill(0);
for (const [a, b] of prerequisites) {
adj[b].push(a);
indegree[a]++;
}
const queue: number[] = [];
for (let i = 0; i < n; i++) if (indegree[i] === 0) queue.push(i);
let finished = 0;
while (queue.length > 0) {
const cur = queue.shift()!;
finished++;
for (const nb of adj[cur])
if (--indegree[nb] === 0) queue.push(nb);
}
return finished === n;finished < numCourses after BFS, some nodes were never reachable with indegree 0 — they are stuck in a cycle.V nodes and E edges?prerequisites = [[1,0],[0,1]] with numCourses = 2, what happens during Kahn's algorithm?numCourses = 4 and prerequisites [[1,0],[2,0],[3,1],[3,2]], what is the earliest course that can be dequeued?numCourses = 5, the finished counter equals 3. What does this mean?