Quick Overview

Given n labeled nodes and directed precedence edges, return an ordering that respects every edge, choosing the lexicographically smallest valid ordering, or an empty list when a cycle makes ordering impossible. It tests topological sorting, cycle detection and deterministic tie-breaking.

Lexicographically Smallest Topological Order of a Dependency Graph

Company: LinkedIn

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Onsite

You are given a dependency graph with `n` nodes labeled `0` to `n - 1` and a list of directed edges, where an edge `[u, v]` means node `u` must come before node `v`. Return an ordering of all `n` nodes in which, for every edge, `u` appears before `v`. If no such ordering exists because the edges contain a cycle, return an empty list. Many graphs have more than one valid ordering. Return the lexicographically smallest one: compare two valid orderings at the first position where they differ; the ordering with the smaller label at that position is the smaller one. ### Function Signature ```python def topological_order(n: int, edges: list[list[int]]) -> list[int]: ``` ### Rules - Every node appears exactly once in the result, including nodes that have no edges. - An edge may be listed more than once; repeats mean the same as a single copy. - A self-loop `[u, u]` is a cycle. - If any cycle exists anywhere in the graph, return `[]`, even if some nodes could still be ordered. ### Constraints - `1 <= n <= 10^5` - `0 <= len(edges) <= 2 * 10^5` - each edge is a pair `[u, v]` with `0 <= u < n` and `0 <= v < n` ### Examples **Example 1** ```text Input: n = 5, edges = [[3, 1], [1, 0], [3, 2], [4, 2]] Output: [3, 1, 0, 4, 2] ``` Only 3 and 4 have no prerequisites, so the ordering starts with 3. After 3, both 1 and 4 are allowed and 1 is smaller; after 1, node 0 is allowed and is smaller than 4. Node 2 must wait for both 3 and 4. **Example 2** ```text Input: n = 3, edges = [[0, 1], [1, 2], [2, 0]] Output: [] ``` The three edges form a cycle, so no valid ordering exists. **Example 3** ```text Input: n = 4, edges = [[2, 0], [2, 0], [1, 3]] Output: [1, 2, 0, 3] ``` The repeated edge `[2, 0]` counts once. Node 0 has the smallest label but must follow 2, and node 3 must follow 1.

Overview: Given n labeled nodes and directed precedence edges, return an ordering that respects every edge, choosing the lexicographically smallest valid ordering, or an empty list when a cycle makes ordering impossible. It tests topological sorting, cycle detection and deterministic tie-breaking.

Read the full LinkedIn Software Engineer interview experience this question came from

You are given a dependency graph with `n` nodes labeled `0` to `n - 1` and a list of directed edges `edges`, where an edge `[u, v]` means node `u` must come before node `v`. Return an ordering of all `n` nodes (a list of labels) in which, for every edge `[u, v]`, `u` appears before `v`. If no such ordering exists because the edges contain a cycle, return an empty list. Many graphs have more than one valid ordering. Return the lexicographically smallest one: compare two valid orderings at the first position where they differ; the ordering with the smaller label at that position is the smaller one. **Rules** - Every node appears exactly once in the result, including nodes that have no edges. - An edge may be listed more than once; repeats mean the same as a single copy. - A self-loop `[u, u]` is a cycle. - If any cycle exists anywhere in the graph, return `[]`, even if some nodes could still be ordered. **Constraints** - `1 <= n <= 10^5` - `0 <= len(edges) <= 2 * 10^5` - each edge is a pair `[u, v]` with `0 <= u < n` and `0 <= v < n` - Every label fits in a signed 32-bit integer (no value exceeds 2^31 - 1). **Example 1** Input: `n = 5, edges = [[3, 1], [1, 0], [3, 2], [4, 2]]` Output: `[3, 1, 0, 4, 2]` Only 3 and 4 have no prerequisites, so the ordering starts with 3. After 3, both 1 and 4 are allowed and 1 is smaller; after 1, node 0 is allowed and is smaller than 4. Node 2 must wait for both 3 and 4. **Example 2** Input: `n = 4, edges = [[2, 0], [2, 0], [1, 3]]` Output: `[1, 2, 0, 3]` The repeated edge `[2, 0]` counts once. Node 0 has the smallest label but must follow 2, and node 3 must follow 1.

Constraints

  • 1 <= n <= 10^5
  • 0 <= len(edges) <= 2 * 10^5
  • each edge is a pair [u, v] with 0 <= u < n and 0 <= v < n
  • edges may repeat (a repeat means the same as one copy) and may include self-loops [u, u], which are cycles
  • every label fits in a signed 32-bit integer

Examples

Input: (5, [[3, 1], [1, 0], [3, 2], [4, 2]])

Expected Output: [3, 1, 0, 4, 2]

Explanation: Source Example 1: 3 is the smallest free node; then 1 beats 4, 0 beats 4, and 2 waits for both 3 and 4.

Input: (3, [[0, 1], [1, 2], [2, 0]])

Expected Output: []

Explanation: Source Example 2: the three edges form a cycle, so no ordering exists.

Hints

  1. Which nodes are allowed to appear first? Think about what must already be placed before a node can appear.
  2. As the first example shows, the set of allowed nodes changes after every placement; at each position, ask which allowed label keeps the ordering smallest.
  3. Decide how you will notice that some node can never be placed, and check that a repeated edge or a self-loop is handled by that same reasoning.

Loading coding console...

Show the approach

Approach

Use Kahn's algorithm with a min-priority queue. Count each node's in-degree over all listed edges (an edge listed k times adds k) and push every node with in-degree 0 into a min-heap. Repeatedly pop the smallest label, append it to the result, and for each listed outgoing edge decrement the target's in-degree, pushing the target when it reaches 0.

Invariant: the heap holds exactly the unplaced nodes whose predecessors are all already placed, i.e. the nodes allowed at the next position of any valid ordering that extends the current prefix. Correctness: every valid ordering extending the prefix must put one of these nodes next, so the smallest of them is the smallest label possible at this position; and because the remaining graph is still acyclic, any allowed choice can be completed to a full valid ordering. Taking the minimum at every position therefore produces the lexicographically smallest ordering.

Cycles: a node on a cycle, or reachable only through one, never reaches in-degree 0 because some predecessor is never placed; a self-loop could only be decremented by the node itself. So fewer than n nodes are placed exactly when a cycle exists anywhere, and the function then returns []. In an acyclic graph some unplaced node always has in-degree 0, so all n nodes are placed.

Duplicates: an edge listed k times adds k to the target's in-degree and is decremented k times when its source is placed, which behaves exactly like a single copy. Edge cases: n = 1 with no edges returns [0]; an empty edge list returns 0..n-1; nodes without edges start in the heap and interleave by label with constrained nodes.

Time complexity:
O(n log n + m), where m = len(edges)
Space complexity:
O(n + m)