Detect cycles and break them in pod dependencies
Company: Together AI
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: nan
Interview Round: Technical Screen
Quick Answer: This question evaluates proficiency with directed graph concepts and dependency resolution, focusing on cycle detection and selecting a single dependency edge whose removal renders the graph acyclic.
Part 1: Detect a Cycle in Pod Dependencies
Constraints
- 0 <= n <= 200000
- 0 <= len(edges) <= 300000
- 0 <= u, v < n for every edge (u, v)
Examples
Input: (4, [(0, 1), (1, 2), (2, 3)])
Expected Output: False
Explanation: The dependencies form a simple chain, so a valid build order exists: 0, 1, 2, 3.
Input: (3, [(0, 1), (1, 2), (2, 0)])
Expected Output: True
Explanation: Every pod depends on another in the cycle 0 -> 1 -> 2 -> 0, so no valid build order exists.
Input: (0, [])
Expected Output: False
Explanation: An empty graph has no nodes and therefore no cycles.
Input: (2, [(1, 1)])
Expected Output: True
Explanation: Pod 1 depends on itself, which is a directed cycle.
Input: (5, [(0, 1), (2, 3)])
Expected Output: False
Explanation: The graph is disconnected, but neither component contains a cycle.
Solution
def solution(n, edges):
from collections import deque
adj = [[] for _ in range(n)]
indegree = [0] * n
for u, v in edges:
adj[u].append(v)
indegree[v] += 1
queue = deque(i for i in range(n) if indegree[i] == 0)
processed = 0
while queue:
node = queue.popleft()
processed += 1
for neighbor in adj[node]:
indegree[neighbor] -= 1
if indegree[neighbor] == 0:
queue.append(neighbor)
return processed != nTime complexity: O(n + m), where m is the number of edges. Space complexity: O(n + m).
Hints
- A directed graph has no cycle if you can produce a full topological ordering.
- Try repeatedly removing nodes with indegree 0. What does it mean if some nodes are never removed?
Part 2: Remove One Dependency to Break All Cycles
Constraints
- 0 <= n <= 2000
- 0 <= len(edges) <= 5000
- 0 <= u, v < n for every edge (u, v)
- If the graph contains cycles, at least one single-edge removal can make the graph acyclic
Examples
Input: (4, [(0, 1), (1, 2), (2, 3)])
Expected Output: True
Explanation: A simple chain has no cycle, so all pods can be built.
Input: (3, [(0, 1), (1, 2), (2, 1)])
Expected Output: False
Explanation: Pods 1 and 2 depend on each other, creating a cycle.
Input: (1, [])
Expected Output: True
Explanation: Edge case: a single pod with no dependencies is always buildable.
Input: (2, [(1, 1)])
Expected Output: False
Explanation: A self-loop is a cycle.
Input: (5, [(0, 1), (2, 3)])
Expected Output: True
Explanation: Disconnected components are fine as long as none contains a cycle.
Solution
def solution(n, edges):
from collections import deque
adj = [[] for _ in range(n)]
indegree = [0] * n
for u, v in edges:
adj[u].append(v)
indegree[v] += 1
q = deque(i for i in range(n) if indegree[i] == 0)
built = 0
while q:
node = q.popleft()
built += 1
for nei in adj[node]:
indegree[nei] -= 1
if indegree[nei] == 0:
q.append(nei)
return built == n
Time complexity: O(n + m), where m = len(edges). Space complexity: O(n + m).
Hints
- Any valid edge to remove must belong to every cycle, so it must be on at least one cycle you detect.
- Find one cycle first, then try removing each edge on that cycle and test whether the remaining graph has a topological ordering.