Skip to content
ΣDSA Patterns
Menu
Language

Topological Sort

Guide 5 of 6 · Path 5 of 6

Interactive

Mental model

A worked animation for this problem. Scrub steps or press space to pause; re-tell the invariant out loud.

Step 1 of 6
1in 02in 03in 2

each BFS layer = 1 semester

Parallel courses: n=3, [1,3] and [2,3]. Any number of ready courses per semester. Min semesters, or −1 on a cycle.

Demo preview: These solutions pass the automated test suite but have not been human-reviewed. Treat trade-offs and prose as draft.

Parallel Courses

Problem (restated)

n courses (1..n) with prerequisites [prev, next]. You may take any number of courses with satisfied prereqs each semester. Min semesters to finish all, or -1 if impossible.

Intuition

Layered Kahn: each BFS layer is one semester. If not all courses taken, cycle → -1.

Approaches

Kahn by semester layers

Unverified
Time O(n + e)Space O(n + e)

Idea. Start with indegree 0; process whole queue level, then increment semester.

Walkthrough. n=3, [[1,3],[2,3]] → 2 semesters.

Trade-offs. Same graph as Course Schedule; answer is longest path length in DAG (+1).

Solution
export function minimumSemesters(n: number, relations: number[][]): number {
  const g: number[][] = Array.from({ length: n + 1 }, () => []);
  const indeg = Array(n + 1).fill(0);
  for (const e of relations) {
    g[e[0]!]!.push(e[1]!);
    indeg[e[1]!]!++;
  }
  let q: number[] = [];
  for (let i = 1; i <= n; i++) if (indeg[i] === 0) q.push(i);
  let sem = 0, taken = 0;
  while (q.length) {
    const next: number[] = [];
    for (const u of q) {
      taken++;
      for (const v of g[u]!) {
        if (--indeg[v]! === 0) next.push(v);
      }
    }
    sem++;
    q = next;
  }
  return taken === n ? sem : -1;
}
export function minimumSemesters(n: number, relations: number[][]): number {
  const g: number[][] = Array.from({ length: n + 1 }, () => []);
  const indeg = Array(n + 1).fill(0);
  for (const e of relations) {
    g[e[0]!]!.push(e[1]!);
    indeg[e[1]!]!++;
  }
  let q: number[] = [];
  for (let i = 1; i <= n; i++) if (indeg[i] === 0) q.push(i);
  let sem = 0, taken = 0;
  while (q.length) {
    const next: number[] = [];
    for (const u of q) {
      taken++;
      for (const v of g[u]!) {
        if (--indeg[v]! === 0) next.push(v);
      }
    }
    sem++;
    q = next;
  }
  return taken === n ? sem : -1;
}

Template connection

Topological sort with level counting.

Reflection