Sweaty Imposter

Course Schedule

MediumTopological SortBlind 75MidOpen on LeetCodeUpdated

You have numCourses courses labeled 0 to numCourses - 1, and an array prerequisites where prerequisites[i] = [a, b] means you must finish course b before you can take course a. Return true if there is some order in which you can finish every course, and false otherwise. Some courses have no prerequisites, and requirements can chain: if 2 needs 1 and 1 needs 0, then 0 must come before both.

Examples

numCourses = 2, prerequisites = [[1,0]] returns true

01
An arrow means 'take this first'. Course 0 comes before course 1.

Course 1 needs course 0, so you take 0 first and then 1.

numCourses = 2, prerequisites = [[1,0],[0,1]] returns false

01
An arrow means 'take this first'. The arrows form a loop, so neither course can go first.

Course 1 needs 0 and course 0 needs 1. Each one waits on the other, so neither can ever be started.

Constraints

  • 1 <= numCourses <= 2000
  • 0 <= prerequisites.length <= 5000

Hints

Hint 1

When is a set of prerequisite dependencies actually finishable?

Hint 2
A pointer toward the approach
Hint 3
The full approach, step by step

Drill This: Your Approach First

Approach

Treat each pair [a, b] as a directed edge b -> a and count each course's in-degree, the number of prerequisites it still waits on. Queue every course with in-degree 0. Repeatedly take one, count it as finished, and decrement the in-degree of each course that depends on it, queuing any that reach 0 (Kahn's algorithm). A course on a cycle never reaches 0, so every course finishes exactly when there's no cycle. O(V + E) time and space, V = numCourses, E = number of pairs.

Time

O(V + E)

Space

O(V + E)

Pitfall

Seeding the queue only from courses that appear in prerequisites: a course in no pair still counts toward numCourses, so check every label 0 to numCourses - 1 for in-degree 0, or the final count comes up short.

Solutions

class Solution {
    public boolean canFinish(int numCourses, int[][] prerequisites) {
        List<List<Integer>> graph = new ArrayList<>();
        for (int i = 0; i < numCourses; i++) graph.add(new ArrayList<>());
        int[] indeg = new int[numCourses];
        for (int[] e : prerequisites) {
            graph.get(e[1]).add(e[0]);
            indeg[e[0]]++;
        }
        Deque<Integer> queue = new ArrayDeque<>();
        for (int i = 0; i < numCourses; i++) if (indeg[i] == 0) queue.offer(i);
        int taken = 0;
        while (!queue.isEmpty()) {
            int c = queue.poll();
            taken++;
            for (int nb : graph.get(c)) {
                if (--indeg[nb] == 0) queue.offer(nb);
            }
        }
        return taken == numCourses;
    }
}
Drill This