Beyond Big O

Dependency cycle detection

Dependency cycle detection

Medium

Solution guide

Reveal solution guide — spoilers

Approach

  1. Build directed adjacency lists for all count nodes, preserving the supplied edge direction.
  2. Use three states per node: unseen, active in the current depth-first traversal, and finished. An edge to an active node proves a cycle; an edge to a finished node does not.
  3. When exploring an unseen node, mark it active, inspect its outgoing edges, then mark it finished only after all descendants finish without finding a cycle.
  4. Start a traversal from every still-unseen node so disconnected components are checked too. Return false only after all components finish.

Why it works

Active nodes form the current ancestor path. An edge back to one closes a directed path into a cycle. Conversely, a directed cycle reached by the traversal must eventually encounter a vertex still active on that path. Finished nodes have already had all reachable outgoing paths examined, so reusing their result avoids false cycles and repeated work.

Complexity

O(V + E) time for V=count nodes and E edges. Adjacency lists use O(V + E) storage; node states and the recursive or explicit traversal stack use O(V) additional space.

Edge cases to check

  • An empty graph has no cycle; a self-loop is a cycle.
  • Repeated identical edges alone do not imply a cycle; they may point to an already finished node.
  • A cycle disconnected from node zero must still be found. A shared descendant in a directed acyclic graph is not a back edge to an active ancestor.
Editor options
Typing preferences

Saved in this browser.

Restoring local drafts…