Parallel Courses

medium graph topological sort bfs

Problem

You are given an integer n (courses 1..n) and a list of prerequisite relations where each relations[i] = [prev, next] means course prev must be taken before course next. In one semester you may study any number of courses whose prerequisites are all already done. Return the minimum number of semesters needed to finish all courses, or -1 if it is impossible (a cycle exists).

Inputn = 5, relations = [[1,3],[2,3],[3,4],[3,5]]
Output3
Semester 1: courses 1 and 2. Semester 2: course 3. Semester 3: courses 4 and 5.

from collections import deque

def minimum_semesters(n, relations):
    indeg = [0] * (n + 1)
    adj = [[] for _ in range(n + 1)]
    for prev, nxt in relations:
        adj[prev].append(nxt)
        indeg[nxt] += 1
    queue = deque(c for c in range(1, n + 1) if indeg[c] == 0)
    semesters, studied = 0, 0
    while queue:
        semesters += 1
        for _ in range(len(queue)):
            c = queue.popleft()
            studied += 1
            for nxt in adj[c]:
                indeg[nxt] -= 1
                if indeg[nxt] == 0:
                    queue.append(nxt)
    return semesters if studied == n else -1
function minimumSemesters(n, relations) {
  const indeg = new Array(n + 1).fill(0);
  const adj = Array.from({ length: n + 1 }, () => []);
  for (const [prev, nxt] of relations) {
    adj[prev].push(nxt);
    indeg[nxt]++;
  }
  let queue = [];
  for (let c = 1; c <= n; c++) if (indeg[c] === 0) queue.push(c);
  let semesters = 0, studied = 0;
  while (queue.length) {
    semesters++;
    const next = [];
    for (const c of queue) {
      studied++;
      for (const nxt of adj[c]) {
        if (--indeg[nxt] === 0) next.push(nxt);
      }
    }
    queue = next;
  }
  return studied === n ? semesters : -1;
}
class Solution {
    public int minimumSemesters(int n, int[][] relations) {
        int[] indeg = new int[n + 1];
        List<List<Integer>> adj = new ArrayList<>();
        for (int i = 0; i <= n; i++) adj.add(new ArrayList<>());
        for (int[] r : relations) { adj.get(r[0]).add(r[1]); indeg[r[1]]++; }
        Deque<Integer> queue = new ArrayDeque<>();
        for (int c = 1; c <= n; c++) if (indeg[c] == 0) queue.add(c);
        int semesters = 0, studied = 0;
        while (!queue.isEmpty()) {
            semesters++;
            for (int sz = queue.size(); sz > 0; sz--) {
                int c = queue.poll();
                studied++;
                for (int nxt : adj.get(c))
                    if (--indeg[nxt] == 0) queue.add(nxt);
            }
        }
        return studied == n ? semesters : -1;
    }
}
int minimumSemesters(int n, vector<vector<int>>& relations) {
    vector<int> indeg(n + 1, 0);
    vector<vector<int>> adj(n + 1);
    for (auto& r : relations) { adj[r[0]].push_back(r[1]); indeg[r[1]]++; }
    queue<int> q;
    for (int c = 1; c <= n; c++) if (indeg[c] == 0) q.push(c);
    int semesters = 0, studied = 0;
    while (!q.empty()) {
        semesters++;
        for (int sz = q.size(); sz > 0; sz--) {
            int c = q.front(); q.pop();
            studied++;
            for (int nxt : adj[c])
                if (--indeg[nxt] == 0) q.push(nxt);
        }
    }
    return studied == n ? semesters : -1;
}
Time: O(n + e) Space: O(n + e)