Limited-time offer: 80% off every plan

See plans

Topological Sorting Coding Interview: Check the Precondition First

A practical walkthrough of topological sorting coding interview questions: how to clarify the prompt, detect cycles, choose an algorithm, derive complexity and narrate every decision.

By Emily Miller13 min read

A topological sorting coding interview question is rarely about memorising an algorithm. It is about whether you notice that the problem is only well defined on a directed acyclic graph, say so before you write code, and then narrate a sensible way to produce an order. Interviewers score the visible reasoning as much as the finished function, so the goal is to think out loud in a sequence someone else can follow.

This article walks through that sequence: what the question is really asking, the questions to ask first, two valid algorithms, how to derive complexity from first principles, and how to recover when something goes wrong mid-answer.

What a Topological Sorting Coding Interview Actually Asks You to Do

A topological order is an ordering of the nodes in a directed graph such that every edge points forward: if there is an edge from A to B, then A appears before B. That is the whole definition. Everything else is consequences.

The first consequence is the precondition. A topological order exists only if the graph is directed and acyclic. If the graph has a cycle, there is no valid ordering, because the cycle would require some node to come before itself. Say this out loud before you write a line of code. It signals that you are checking assumptions rather than reaching for a familiar tool.

Two everyday framings make the definition concrete. Course prerequisites: if CS201 requires CS101, then CS101 must be scheduled earlier. Build dependencies: if module A imports module B, B must compile first. In both cases the edges encode "must come before", and the ordering is the schedule.

The reason interviewers like this question is that it separates people who pattern-match from people who reason. The prompt is often vague. The graph may or may not have a cycle. The expected output may be an ordering, a boolean, or both. Your job is to turn that vagueness into a bounded problem before you start typing.

Clarifying Questions to Ask Before You Code

A short, well-chosen set of questions buys you goodwill and prevents wasted work. Ask them in a batch, then wait.

  • Is the graph guaranteed to be acyclic, or should I detect cycles and report them?
  • What form is the input in: an adjacency list, an edge list, a matrix, or something I build myself?
  • Do you want any valid ordering, or a specific one such as the lexicographically smallest?
  • Should I return the ordering, a boolean, or both? What should happen for an empty graph or a single node?
  • Are node labels integers, strings, or objects I need to map to indices?

Each answer changes the shape of the solution. If the graph might contain a cycle, your function needs a way to report that. If the input is an edge list, you have a graph-building step that costs time and space of its own. If a specific ordering is required, a plain queue is not enough and you need a priority queue.

Stating these questions also gives you a natural moment to say what you will assume if the interviewer waves the question away. "I'll assume an adjacency list, no cycles, and any valid ordering is fine" is a sentence that makes the rest of your answer auditable.

Kahn's Algorithm: Build the Order by Removing Sources

Kahn's algorithm is the one most people find easiest to explain, because it matches the intuition directly: repeatedly take a node with no remaining incoming edges.

Describe it in words first, before any code:

  1. Compute the in-degree of every node: how many edges point into it.
  2. Put every node with in-degree zero into a queue. These are the sources.
  3. Pop a node, append it to the result, and for each of its neighbours, decrement that neighbour's in-degree. If a neighbour's in-degree hits zero, push it.
  4. Repeat until the queue is empty.
  5. If the result contains fewer nodes than the graph, a cycle exists.

That last step is the part candidates forget. The algorithm cannot finish if some nodes are stuck behind a cycle, so the size check is the cycle detector. Say it plainly: "If the output is shorter than the node count, the remaining nodes are exactly the ones involved in or downstream of a cycle."

A Small Worked Example, Narrated

Take six nodes, 0 through 5, with edges 5→2, 5→0, 4→0, 4→1, 2→3, 3→1.

In-degrees: 0 has 2, 1 has 2, 2 has 1, 3 has 1, 4 has 0, 5 has 0.

Here is the kind of narration that shows your reasoning rather than hiding it:

"I'm seeding the queue with the two sources, 4 and 5, because their in-degree is zero — nothing has to come before them."

Queue starts as [4, 5]. Pop 4, append it, and decrement 0 and 1. Node 0 drops to 1, node 1 drops to 1. Queue is [5].

"Popping 4 releases its neighbours but doesn't free either one yet, so the queue stays at one node."

Pop 5, append it, decrement 2 and 0. Node 2 drops to 0, so it joins the queue; node 0 drops to 0, so it joins too. Queue is [2, 0].

"Now two nodes are ready at once, so I'll note that the ordering isn't unique here — any of these choices is valid."

Pop 2, append it, decrement 3, which reaches 0 and joins. Queue is [0, 3]. Pop 0, append it, nothing changes. Pop 3, append it, decrement 1, which reaches 0 and joins. Pop 1 and append it.

Result: 4, 5, 2, 0, 3, 1. Six nodes out of six, so no cycle. Trace this out loud in an interview and you have demonstrated the algorithm without reciting it.

The same structure answers "can this schedule be completed?" — you just return whether the output length equals the node count, and skip the ordering entirely.

DFS Post-Order: The Other Route to the Same Answer

The depth-first approach reaches the same destination from the other end. The idea: finish a node only after all of its descendants are finished, then prepend it to the result.

Mechanically, you mark each node as unvisited, in progress, or done. When you enter a node, mark it in progress. Recurse into each neighbour. If you ever meet a neighbour that is in progress, you have found a back edge and therefore a cycle. When all neighbours are done, mark the node done and add it to the front of the output list.

The three-colour marking is doing real work here, not decoration. Without the "in progress" state you cannot distinguish a node you are still exploring from one you finished earlier, and you will either miss cycles or report false ones.

Choosing Between Them Out Loud

Both algorithms produce a valid topological ordering, which is why an interviewer may accept either. The interesting part of your answer is the reasoning for your choice, so say it rather than deciding silently.

Kahn's algorithm tends to read more naturally when the question is about scheduling, because the in-degree queue mirrors "what is ready to run now". It also detects cycles without any extra bookkeeping. DFS post-order tends to read more naturally when the graph is already being traversed for another reason, or when you want to reuse a depth-first skeleton you have already written. Its main caveat is recursion depth: on a very large graph, a recursive DFS can exhaust the call stack, and an explicit stack is the safer version. Mention that caveat even if you do not need it.

Talking Through Complexity Without Guessing

Derive the complexity rather than recalling it. That way you can adapt when the interviewer changes a constraint.

For time: every node is enqueued once and popped once, and every edge is examined once when its source node is processed. Each of those operations is constant work. So the running time is O(V + E), where V is the number of nodes and E the number of edges.

For space: the adjacency structure holds every edge, so it is O(V + E). The in-degree array is O(V). The queue or the recursion stack is O(V) in the worst case. Total: O(V + E).

Then separate the two costs. Building the graph from an edge list is a pass over the input, so it is O(E) — but it is a distinct step from the traversal, and conflating them makes your analysis sound memorised. Practise the sentence: "That assumes an adjacency list is already built; if you hand me an edge list, there is an O(E) setup pass first."

For DFS, add the recursion-depth point: the stack depth is bounded by the longest path, which can be O(V), and an iterative version trades the call stack for an explicit one.

Common Traps and How to Recover Mid-Answer

Most lost points on this question come from a small set of mistakes. Knowing them in advance makes them recoverable.

  • Forgetting the cycle check and returning a partial ordering as if it were complete. The fix is one comparison: result length against node count.
  • Confusing in-degree with out-degree when seeding the queue. In-degree counts incoming edges; sources have none.
  • Mutating the graph while iterating over it, then losing track of which state you are in. Prefer separate structures over in-place edits.
  • Assuming the input is an adjacency list when it is not, then discovering it halfway through the code.

When you get stuck, do not go quiet. Narrate the smallest failing example: "With these three nodes and this edge, I expected the cycle branch to trigger and it did not." Then state what you think is wrong and correct it in place. A visible, calm correction usually reads better than silent stalling, because the interviewer can see that your debugging process is sound even when the first attempt is not.

Follow-Up Questions You Should Expect

Interviewers often extend the problem once the base version works. Answer by naming the change in constraints first, then the change in approach.

All valid orderings. If the graph has several sources at once, any of them can go next. To enumerate every ordering you branch on each available source, which is exponential in the worst case. Say that plainly rather than pretending it is cheap.

The lexicographically smallest ordering. Swap the queue for a min-heap keyed on node label. The traversal is unchanged; only the selection step changes, and the cost picks up a logarithmic factor.

Uniqueness. An ordering is unique exactly when the queue never holds more than one node at a time. That is a clean thing to state and a good sign you understand the algorithm rather than the code.

Streaming edges. If edges arrive over time, you cannot precompute in-degrees once. You maintain them incrementally and re-check which nodes have become sources.

Graphs too large for memory. You need an external or approximate approach; the honest answer is to describe what you would store on disk and what you would keep in memory, rather than inventing a textbook algorithm.

The same reasoning transfers directly to course scheduling, task ordering and dependency resolution. The habit of clarifying before coding carries over to other question types too, as in Python Interview Questions: Concepts and Trade-Offs and Sorting Coding Interview: Reason Through the Algorithm Out Loud.

How to Practise This Out Loud

Reading about an algorithm is not the same as being able to explain it under mild pressure. The skill is verbal, so practise it verbally — and treat a topological sorting coding interview as a speaking exercise as much as a coding one.

  1. Rehearse the full arc: restate the problem, ask your clarifying questions, name your approach, code it, test it on the small example, then state the complexity.
  2. Record yourself and listen back. The useful signal is not whether you were right; it is where you went silent instead of narrating a decision.
  3. Re-solve the same problem a day later without notes. If the reasoning stuck, it will come back quickly. If you are reciting, it will not.
  4. Work a small set of related problems — course schedule, build order, task sequencing — so you practise the pattern rather than memorising one instance.
  5. Keep the explanations honest. The point of practice is to become someone who can reason about a graph in front of another person, not to have a script ready.

One takeaway worth carrying into the interview: the ordering is the easy part; the reasoning that gets you there is what is being assessed. Say what you are checking, say why, and say what you would do differently if the constraints changed.

Frequently asked questions

Do I need to know both Kahn's algorithm and the DFS approach for a coding interview?

Not necessarily, but you should be able to explain the trade-off. Kahn's algorithm tracks in-degrees and removes sources, which makes cycle detection fall out of a length comparison. DFS post-order finishes each node after its descendants and prepends it, using an in-progress marking to catch back edges. Both produce a valid ordering. Being able to say which one you find clearer, and why, is often more impressive than knowing both by rote.

What is the time complexity of topological sort, and how do I explain it clearly?

O(V + E), where V is the number of nodes and E the number of edges. Derive it rather than reciting it: every node is enqueued and popped once, and every edge is examined once when its source is processed, so each element is touched a constant number of times. If the input is an edge list rather than an adjacency list, add a separate O(E) pass to build the graph, and say that it is a distinct step.

How do I tell the interviewer that the graph contains a cycle?

In Kahn's algorithm, compare the length of the produced ordering with the number of nodes. If the ordering is shorter, the remaining nodes are involved in or downstream of a cycle, and no topological order exists. In the DFS approach, a cycle shows up as an edge to a node currently marked in progress. State the finding plainly, then say what the function should return instead.

What if the interviewer asks for all valid topological orderings?

Describe the change in constraints first. Instead of taking whichever source is at the front of the queue, you branch on every available source at each step and collect each complete ordering. That is exponential in the worst case, so say so rather than implying it is as cheap as the base algorithm. If they only want the lexicographically smallest ordering, the change is smaller: use a min-heap instead of a queue.

Is topological sorting asked in interviews for non-graph roles?

It appears most often in software engineering and data-oriented interviews, but the underlying reasoning — checking preconditions, choosing between valid approaches, deriving complexity — is asked in many forms. The transferable skill is turning a vague prompt into a bounded problem before writing code, and that shows up across roles and question types.

How long should I spend on this question before asking for a hint?

It depends on the format, but a reasonable guide is to spend the first few minutes clarifying and outlining, and to speak up if you are genuinely stuck rather than going silent. Narrating the smallest failing example and what you expected usually moves things forward. A visible, calm correction tends to read better than a long pause, because it shows your debugging process.

Rehearse explaining your reasoning aloud