Katkat

Resolve Package Dependencies with Cycle Detection

AmazonSoftware Engineer · Technical Screen

Last updated

This problem tests your ability to perform a topological sort on a directed graph while identifying cyclic dependencies to ensure a safe build order.

Problem Statement

You are tasked with writing a build system component that resolves package dependencies. You are given a dictionary where keys are package names (strings) and values are lists of their direct dependencies (strings).

Implement a function resolve_build_order(package, dependency_map) that returns a list of all packages required to install the target package, ordered such that every dependency appears before the package that requires it. If a cycle is detected, or if a dependency is required but missing from the dependency_map, the function should raise an error or return an empty list/appropriate indicator.

Function Signature

def resolve_build_order(target, dependency_map):
    # Returns a list of strings representing the installation order
    pass

Constraints

  • dependency_map contains up to 10,000 packages.
  • Cycles must be detected and handled (do not enter an infinite loop).
  • A package missing from the keys of dependency_map is considered a leaf node with no dependencies.

Example 1

Input: dependency_map = {'A': ['B', 'C'], 'B': ['C'], 'C': []}, target = 'A' Output: ['C', 'B', 'A'] Explanation: 'C' is a dependency of 'B' and 'A', so it must be installed first. 'B' depends on 'C', and 'A' depends on 'B' and 'C'.

Example 2

Input: dependency_map = {'A': ['B'], 'B': ['A']}, target = 'A' Output: Error (Cycle Detected)

Edge Cases

  • Disconnected components that are not required by the target.
  • Chains of dependencies of depth > 1000.
  • Target package has no dependencies.

Hints

Hint 1

Consider representing the dependencies as a directed graph and performing a Depth First Search (DFS).

Hint 2

Use a tri-state approach (unvisited, visiting, visited) to keep track of nodes to detect cycles during your traversal.

Hint 3

The build order is equivalent to the reverse of the post-order traversal of the dependency graph.

Follow-up questions

  • How would you modify your solution to support parallel installation of packages that do not share dependencies?
  • What are the space and time complexity trade-offs if the dependency graph is extremely sparse versus extremely dense?
  • How would you handle a scenario where packages might have multiple versions, and two different packages require different versions of the same library?