Maintain an Out-of-Order Step Progress Tree
Ai2Software Engineer · Technical ScreenLast updated
This problem tests tree reconstruction from a stream of out-of-order parent-child updates, requiring efficient hierarchical state management and cycle detection.
Problem Statement
You are building a real-time progress tracker for complex workflows. You receive a stream of StepUpdate events, where each event updates the state of a step or defines its parent relationship. Steps can be created in any order, and parent references may refer to steps that have not been seen yet.
An event is defined as:
{step_id: str, status: str, parent_id: str | None, timestamp: int}.
Requirements
- Hierarchy: If a step is assigned a
parent_id, it becomes a child of that step. If a step is reassigned to a new parent, it moves in the tree. - Out-of-order: Updates for a child might arrive before the parent exists, or later updates might arrive with older timestamps. Always honor the state of the update with the highest
timestampfor a specificstep_id. - Cycle Prevention: If a
parent_idassignment creates a cycle, ignore that specific assignment (keep the previous valid parent) and log an error. - Snapshot: Implement a method
get_tree()that returns a nested dictionary representation of the current valid forest, where keys arestep_idand values are their respective children.
Function Signature
class ProgressTracker:
def update(self, event: dict) -> None:
# Update internal state with new event
def get_tree(self) -> dict:
# Returns the current forest representation
Constraints
step_idis unique.- A step can have at most one parent.
- Updates are processed sequentially by the system, but the
timestampfield determines which update is considered the "latest" state for a givenstep_id. - You must handle orphan nodes (steps whose parent does not exist yet) by keeping them in the forest until their parent arrives.
Example
# Update 1: {step_id: "B", parent_id: "A", timestamp: 10}
# Update 2: {step_id: "A", parent_id: None, timestamp: 5}
# Result of get_tree(): {"A": ["B"]}
Edge Cases
- A step claiming to be its own parent (direct cycle).
- A parent ID that never appears in the event stream.
Hints
Hint 1
Maintain a map of `step_id` to its current `latest_event` to ensure only the most recent data is used.
Hint 2
Use an adjacency list to track children and a separate map to track the current parent for quick lookup and cycle validation.
Hint 3
When processing a new `parent_id` for a node, perform a search from the target parent upwards to the root to ensure the node is not already an ancestor of the target parent.
Follow-up questions
- How would you optimize the `get_tree()` call if the tree structure is massive but only a small branch changes?
- How would you ensure thread safety if multiple threads are calling `update()` concurrently?
- What changes would be required if we needed to support multiple parents per step (a Directed Acyclic Graph instead of a tree)?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.