Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Coding Interview Patterns  Module 21 – Topological sort and DAGs

Smallest and unique topological orders

Find the smallest topological order with a min-heap, test whether only one order exists, and decide sequence reconstruction from partial rankings.

  • Intermediate
  • 35 minutes
  • Examples run with Python 3.14.8, Pyodide 314.0.7, Node.js 24.21.0, quickjs 0.32.0, Java 25, Clang 21.0.0 and Go 1.27.1
  • By MySmartCoPilot
Free intro, Pro: 8 of 35 minutes free
Free: Three problems: speakers, one order, and a ranking · The brute force: test every order · What to notice. With a pass: the other 13 sections and 3 interview answers, about 27 minutes.

What you will learn

  • Compute the lexicographically smallest topological order with a min-heap
  • Check whether exactly one topological order exists
  • Decide whether a set of partial rankings forces one full ranking
  • Prove that taking the smallest ready node is always safe
  • Distinguish the smallest order from the order that puts small numbers early

Before you start

What you’ll learn · Before you start

What you will learn

  • Compute the lexicographically smallest topological order with a min-heap
  • Check whether exactly one topological order exists
  • Decide whether a set of partial rankings forces one full ranking
  • Prove that taking the smallest ready node is always safe
  • Distinguish the smallest order from the order that puts small numbers early

Before you start

On this page

Most directed acyclic graphs have many topological orders, so problems add a rule: return the smallest, the one that comes first when orders are compared number by number, or say whether only one order exists. Both questions turn on the moment in Kahn’s algorithm when more than one node is ready. The smallest order always takes the smallest ready node, which a min-heap hands out in O(log n) time. Unique topological orders are those in which that moment never comes: at every step exactly one node is ready.

Three problems: speakers, one order, and a ranking

Problem A: the smallest order. Speakers are numbered 0 to n − 1, and each pair (a, b) in before means that a speaks before b. Return the order that keeps every pair and comes first number by number, or [] if none does. Limits: up to 100,000 speakers and 200,000 pairs.

  • smallest_order(6, [(3, 0), (4, 0), (5, 2), (2, 1)]) gives [3, 4, 0, 5, 2, 1]. Kahn’s queue gives [3, 4, 5, 0, 2, 1], which is valid but larger in the third place.
  • With (1, 5) added, the pairs contain a loop: [].

Problem B: one order or several? Return the order if it is the only one, else nothing. The speakers’ pairs allow 40 orders; adding (3, 4) and (0, 5) leaves exactly one, [3, 4, 0, 5, 2, 1].

Problem C: sequence reconstruction. Referees report how some players of a tournament finished, each report a list in finishing order. Is the ranking seq of all n players the only one that keeps every report? With seq = [0, 1, 2, 3], the reports [0, 1, 3] and [1, 2, 3] say yes; [0, 1, 3] and [0, 2, 3] say no, since [0, 2, 1, 3] keeps both.

Six speakers with an arrow from each speaker to those who must come after; speakers 3, 4 and 5 wait for nobody.speaker 3waits for nobodyspeaker 4waits for nobodyspeaker 5waits for nobodyspeaker 0waits for 3 and 4speaker 2waits for 5speaker 1waits for 2

The speakers of problem A and who waits for whom

Text description of the diagram

The diagram shows six speakers, numbered 0 to 5, as boxes, with an arrow from a speaker to every speaker who must come after them.

  1. Speakers 3, 4 and 5 wait for nobody. Their boxes have double borders: at the start, any of the three may speak first.
  2. Speaker 0 waits for speakers 3 and 4, so arrows lead to it from both.
  3. Speaker 2 waits for speaker 5, and speaker 1 waits for speaker 2, so 5, 2 and 1 form a chain.

The pairs leave many orders open: three speakers can start, and the chain 5, 2, 1 can be interleaved with 3, 4 and 0 in many ways. The smallest order, compared number by number, starts with 3.

The brute force: test every order

Generate the orders of 0 to n − 1 in increasing order and test each one: the first that keeps every pair is the smallest, and counting all that do answers whether only one exists.

Every order tested, for the speakers and for chains Python · brute/all_orders.py
"""The brute force: try every order of the speakers, in increasing order, and test each against the constraints."""
from itertools import permutations


def valid(order, before):
    at = {v: i for i, v in enumerate(order)}
    return all(at[a] < at[b] for a, b in before)


def first_and_count(n, before):
    """The first valid order in increasing order, how many orders were tried to find it, and how many are valid."""
    first, tried, count = None, 0, 0
    for order in permutations(range(n)):  # permutations of 0..n-1 come out in increasing order
        if first is None:
            tried += 1
        if valid(order, before):
            count += 1
            if first is None:
                first = list(order)
    return first, tried, count


speakers = [(3, 0), (4, 0), (5, 2), (2, 1)]  # (a, b): speaker a speaks before speaker b
first, tried, count = first_and_count(6, speakers)
print(f"speakers: first valid order {first}, found after {tried} of 720 orders; {count} valid orders in all")
first, tried, count = first_and_count(6, speakers + [(3, 4), (0, 5)])
print(f"with 3 before 4 and 0 before 5 added: first {first}, {count} valid order")

print("\nTo show that only one order is valid, the brute force has to test every order:")
for n in (6, 7, 8, 9):
    first, tried, count = first_and_count(n, [(i, i + 1) for i in range(n - 1)])
    total = sum(1 for _ in permutations(range(n)))
    print(f"a chain of {n} speakers: {count} valid order among {total:,} tested")

Output

speakers: first valid order [3, 4, 0, 5, 2, 1], found after 438 of 720 orders; 40 valid orders in all
with 3 before 4 and 0 before 5 added: first [3, 4, 0, 5, 2, 1], 1 valid order

To show that only one order is valid, the brute force has to test every order:
a chain of 6 speakers: 1 valid order among 720 tested
a chain of 7 speakers: 1 valid order among 5,040 tested
a chain of 8 speakers: 1 valid order among 40,320 tested
a chain of 9 speakers: 1 valid order among 362,880 tested

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 all_orders.py

The smallest order of the speakers turns up after 438 of the 720 orders. Proving an order unique is worse, because every order must be tested: 362,880 for a chain of 9 speakers, and 20! ≈ 2.4 × 10¹⁸ for 20, while the limits allow 100,000.

What to notice

Kahn’s algorithm may take any ready node next, and all three problems are rules about that choice:

  • A min-heap of ready nodes hands out the smallest one, which gives the smallest order.
  • The uniqueness test stops as soon as two nodes are ready at once, so it finds unique topological orders in one run.
  • Reconstruction checks that every two neighbours in the ranking appear side by side in some report.
  • Putting small numbers early is a different rule: take the largest ready node of the reversed pairs.

The smallest order with a min-heap, step by step Pro: opens with a Pro, Premium or Ultimate pass

In this part:

  • Why taking the smallest ready node is always safe: the proof
  • When exactly one order exists, and the proof
  • Sequence reconstruction, step by step
  • Dry runs on the speakers and the reports
  • The code in five languages
  • How much work it does
  • Edge cases and six bugs, found on the smallest inputs
  • Variants: the largest order, two orders compared, small numbers early, counting orders
  • Exercise: the smallest order
    • The smallest order that keeps every pair
  • A practice set with sample answers
  • Check yourself
  • Interview questions
    • Kahn's algorithm with a min-heap and with a max-heap returns the same order. What does that tell you?
    • Why does taking the smallest ready node at every step give the lexicographically smallest topological order? A colleague worries that a small choice now could force a larger number later.
    • A league publishes a final ranking of 120 teams and says it follows from 400 head-to-head results, each one a winner placed above a loser. How do you check that the results force exactly this ranking, and what do you report when they do not?
    • Jobs are numbered 1 to n, and some must run before others. Operations wants job 1 as early as possible, then job 2 as early as possible given that, and so on. A teammate runs Kahn's algorithm with a min-heap. Why is that wrong, and what is right?
  • Key takeaways

5 runnable examples (C++, Go, Java, JavaScript, Python) · 1 exercise with sample tests · 3 interview answers · about 25 minutes

Opening this part with your pass…

This part opens with any MySmartCoPilot pass.

  • Pro pass · 1 week₹79$2.99
  • 30 days₹179$5.99
  • 1 year₹1,699$45

One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.