Return valid task order from prerequisites
Company: Netflix
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Onsite
Quick Answer: This question evaluates proficiency in graph algorithms, notably topological sorting and cycle detection, as well as algorithmic complexity analysis and handling of dependency constraints.
Part 1: Return one valid execution order of all tasks
Constraints
- 0 <= n <= 100000
- 0 <= len(dependencies) <= 200000
- 0 <= a, b < n for every dependency (a, b)
- All dependency pairs are distinct
- The dependency graph is guaranteed to be acyclic for this part
Examples
Input: (4, [(0, 1), (1, 2), (2, 3)])
Expected Output: [0, 1, 2, 3]
Explanation: There is only one valid order because each task depends on the previous one.
Input: (4, [(0, 2), (1, 2), (2, 3)])
Expected Output: [0, 1, 2, 3]
Explanation: Tasks 0 and 1 can swap places, but both must appear before 2, and 2 must appear before 3. This is one valid answer.
Input: (3, [])
Expected Output: [0, 1, 2]
Explanation: With no dependencies, any permutation is valid. This is one valid answer.
Input: (0, [])
Expected Output: []
Explanation: There are no tasks to schedule.
Hints
- Count how many prerequisites each task has.
- Start with every task whose prerequisite count is 0, and remove tasks layer by layer.
Part 2: Return an empty list if the dependency graph contains a cycle
Constraints
- 0 <= n <= 100000
- 0 <= len(dependencies) <= 200000
- 0 <= a, b < n for every dependency (a, b)
- All dependency pairs are distinct
Examples
Input: (3, [(0, 1), (1, 2)])
Expected Output: [0, 1, 2]
Explanation: This graph is acyclic, so a full ordering exists.
Input: (3, [(0, 1), (1, 2), (2, 0)])
Expected Output: []
Explanation: The dependencies form a cycle, so no valid ordering exists.
Input: (1, [(0, 0)])
Expected Output: []
Explanation: A self-loop is also a cycle.
Input: (4, [(0, 1), (2, 3)])
Expected Output: [0, 2, 1, 3]
Explanation: The graph has two independent chains. This is one valid ordering.
Input: (0, [])
Expected Output: []
Explanation: There are no tasks, so the valid order is empty.
Hints
- A topological ordering exists only if you can repeatedly remove a task with indegree 0.
- After processing, compare how many tasks you placed in the order versus n.
Part 3: Return the lexicographically smallest valid execution order
Constraints
- 0 <= n <= 100000
- 0 <= len(dependencies) <= 200000
- 0 <= a, b < n for every dependency (a, b)
- All dependency pairs are distinct
Examples
Input: (4, [(0, 2), (1, 2)])
Expected Output: [0, 1, 2, 3]
Explanation: Initially tasks 0, 1, and 3 are available. Choosing the smallest available task each time gives the lexicographically smallest order.
Input: (6, [(2, 3), (1, 3), (0, 4)])
Expected Output: [0, 1, 2, 3, 4, 5]
Explanation: This is the smallest order that respects all three dependencies.
Input: (2, [(0, 1), (1, 0)])
Expected Output: []
Explanation: The graph contains a cycle.
Input: (0, [])
Expected Output: []
Explanation: There are no tasks to schedule.
Input: (4, [])
Expected Output: [0, 1, 2, 3]
Explanation: With no dependencies, the lexicographically smallest permutation is the sorted order.
Hints
- When several tasks are ready at the same time, always choose the smallest label first.
- A min-heap is a good way to repeatedly extract the smallest available task.
Part 4: Return all valid topological orders
Constraints
- 0 <= n <= 10
- 0 <= len(dependencies) <= n * (n - 1) / 2
- 0 <= a, b < n for every dependency (a, b)
- All dependency pairs are distinct
Examples
Input: (3, [(0, 2), (1, 2)])
Expected Output: [[0, 1, 2], [1, 0, 2]]
Explanation: Task 2 must be last. Tasks 0 and 1 can appear in either order.
Input: (3, [])
Expected Output: [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
Explanation: With no dependencies, every permutation is valid.
Input: (2, [(0, 1), (1, 0)])
Expected Output: []
Explanation: A cycle means there are no valid topological orders.
Input: (0, [])
Expected Output: [[]]
Explanation: There is exactly one ordering of zero tasks: the empty ordering.
Input: (1, [])
Expected Output: [[0]]
Explanation: A single task has exactly one valid order.
Hints
- Use backtracking: at each step, try every currently available task with indegree 0.
- After exploring one choice, undo the indegree updates before trying the next choice.