Can every task finish, given its prerequisites?

Graphs Mid-level Python 3.13+ Kotlin 2.4+ Reviewed By Best Latest Apps

Pick the fix

Kahn's algorithm finishes with 3 of 5 tasks done. What does that tell you?

Options

Choose an answer, then open Show answer below to check it.

Show answer

Answer: A The other two tasks are on a cycle or wait on one

Right: their in-degree never reaches zero because a loop of rules blocks them.

A task stays blocked only if something it waits on can never finish, and that only happens around a loop.

Why not the others?
  • B The graph is disconnected. Disconnected parts are fine; each part's unblocked tasks start in the queue.
  • C The queue was processed in the wrong order. Any order of ready tasks finishes everything when there is no cycle.
Tasks 0 to 4 with five rules are taken as soon as nothing blocks them; a second set of rules with a loop leaves tasks stuck.

Steps come from running the Python solution.

Text version

No loop:

Nodes [0, 1, 2, 3, 4]; edges 0→1, 0→2, 1→3, 2→3, 3→4.

  1. Visit 0, in-degrees [0, 0, 0, 2, 1]. Take 0; frees 1, 2
  2. Visit 1, in-degrees [0, 0, 0, 1, 1]. Take 1
  3. Visit 2, in-degrees [0, 0, 0, 0, 1]. Take 2; frees 3
  4. Visit 3, in-degrees [0, 0, 0, 0, 0]. Take 3; frees 4
  5. Visit 4, in-degrees [0, 0, 0, 0, 0]. Take 4

Result: true

A loop between 1 and 2:

Nodes [0, 1, 2, 3]; edges 0→1, 1→2, 2→1, 2→3.

  1. Visit 0, in-degrees [0, 1, 1, 1]. Take 0
  2. Visit nothing. 3 nodes never reach in-degree 0: there is a cycle

Result: false

30-second answer

Count, for each task, how many rules still block it (its in-degree). Start with the unblocked tasks; each time one finishes, unblock the tasks that waited on it. If every task finishes, the rules allow an order. If some never become unblocked, they sit on a cycle or wait on one. O(V + E) time and space.

Practise saying it · 60 s. No recording, just a timer

Explain how to decide whether all tasks can finish.

Say your answer out loud, then check which of these points you covered:

  • In-degrees
  • Queue of unblocked tasks
  • Leftovers mean a cycle

Deep dive

This is Kahn's algorithm for topological order; recording the finish order gives a valid schedule.

DFS with three colours (unvisited, in progress, done) finds cycles too: an edge to an in-progress node is a cycle.

Duplicate rules are fine as long as in-degrees count each copy.

Python solution Ran on Python 3.13.5 · mypy --strict
Python 3.13
from collections import deque


def can_finish(n: int, rules: list[list[int]]) -> bool:
    after: list[list[int]] = [[] for _ in range(n)]
    waiting = [0] * n
    for before, task in rules:
        after[before].append(task)
        waiting[task] += 1
    ready = deque(t for t in range(n) if waiting[t] == 0)
    done = 0
    while ready:
        t = ready.popleft()
        done += 1
        for nxt in after[t]:
            waiting[nxt] -= 1
            if waiting[nxt] == 0:
                ready.append(nxt)
    return done == n

Kotlin Ran on Kotlin 2.4.21 · JDK 21.0.12.1
Kotlin 2.4
fun canFinish(n: Int, rules: List<List<Int>>): Boolean {
    val after = List(n) { mutableListOf<Int>() }
    val waiting = IntArray(n)
    for ((before, task) in rules) {
        after[before].add(task)
        waiting[task]++
    }
    val ready = ArrayDeque((0 until n).filter { waiting[it] == 0 })
    var done = 0
    while (ready.isNotEmpty()) {
        val t = ready.removeFirst()
        done++
        for (nxt in after[t]) {
            waiting[nxt]--
            if (waiting[nxt] == 0) ready.addLast(nxt)
        }
    }
    return done == n
}

Common mistakes

  • Treating the rules as undirected, which reports cycles that are not there.
  • Reading [a, b] the wrong way round; check the direction with the interviewer.

Senior take & follow-ups

Explain what leftover tasks mean (a cycle). That one sentence proves the algorithm is correct.

Follow-up questions

Think of your answer first, then open the hint.

  1. How do you return a valid order?

    Show hint

    Append each task as it is taken from the queue.

  2. What if you also want the fewest rounds when unblocked tasks run in parallel?

    Show hint

    Process the queue in layers; the number of layers is the answer.

See it animated on iPhone (Topological Sort in DSA Master - Data & Algorithms)

What each operation costs: Breadth First Search · Depth First Search · Topological Sort · Dijkstra Algorithm

From the author

DSA Master - Data & Algorithms

Free on iPhone and iPad: watch 50+ data structures and algorithms step through animations, run the code in the playground, and try the daily challenge.

Suggest a fix if something here is wrong or out of date.