Build span trees from unordered trace spans
Company: Datadog
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates skill in reconstructing hierarchical relationships from unordered span records, testing understanding of tree structure assembly, orphan/root detection, and ordering children by timestamp within the Coding & Algorithms domain.
Constraints
- 0 <= len(spans) <= 200000
- Each `span_id` is unique
- `parent_id` is either None or a string
- -10^9 <= start_time <= 10^9
- Evaluation inputs do not contain cycles in the parent relationships
Examples
Input: [{'span_id':'span_4','parent_id':'span_2','start_time':500}, {'span_id':'span_2','parent_id':'span_1','start_time':500}, {'span_id':'span_5','parent_id':'span_6','start_time':600}, {'span_id':'span_1','parent_id':None,'start_time':300}, {'span_id':'span_7','parent_id':None,'start_time':1000}, {'span_id':'span_3','parent_id':'span_1','start_time':300}]
Expected Output: [{'span_id':'span_1','parent_id':None,'start_time':300,'children':[{'span_id':'span_3','parent_id':'span_1','start_time':300,'children':[]}, {'span_id':'span_2','parent_id':'span_1','start_time':500,'children':[{'span_id':'span_4','parent_id':'span_2','start_time':500,'children':[]}]}]}, {'span_id':'span_5','parent_id':'span_6','start_time':600,'children':[]}, {'span_id':'span_7','parent_id':None,'start_time':1000,'children':[]}]
Explanation: The input is unordered. `span_1` is a real root, `span_5` is an orphan because `span_6` is missing, and `span_7` is another root. Children are sorted by `start_time`, so under `span_1`, `span_3` comes before `span_2`.
Input: []
Expected Output: []
Explanation: An empty input produces an empty forest.
Input: [{'span_id':'root','parent_id':None,'start_time':42}]
Expected Output: [{'span_id':'root','parent_id':None,'start_time':42,'children':[]}]
Explanation: A single span with no parent is a root and has no children.
Input: [{'span_id':'b','parent_id':'a','start_time':5}, {'span_id':'c','parent_id':'a','start_time':5}, {'span_id':'a','parent_id':None,'start_time':1}, {'span_id':'x','parent_id':'missing','start_time':1}]
Expected Output: [{'span_id':'a','parent_id':None,'start_time':1,'children':[{'span_id':'b','parent_id':'a','start_time':5,'children':[]}, {'span_id':'c','parent_id':'a','start_time':5,'children':[]}]}, {'span_id':'x','parent_id':'missing','start_time':1,'children':[]}]
Explanation: Both `a` and `x` are roots with the same `start_time`, so their relative order follows input order among roots. Children `b` and `c` also share the same `start_time`, so their input order is preserved.
Input: [{'span_id':'child','parent_id':'root','start_time':20,'service':'api'}, {'span_id':'orphan','parent_id':'zzz','start_time':5,'service':'worker'}, {'span_id':'grand','parent_id':'child','start_time':30,'service':'db'}, {'span_id':'root','parent_id':None,'start_time':10,'service':'frontend'}]
Expected Output: [{'span_id':'orphan','parent_id':'zzz','start_time':5,'service':'worker','children':[]}, {'span_id':'root','parent_id':None,'start_time':10,'service':'frontend','children':[{'span_id':'child','parent_id':'root','start_time':20,'service':'api','children':[{'span_id':'grand','parent_id':'child','start_time':30,'service':'db','children':[]}]}]}]
Explanation: This case shows that extra fields such as `service` must be preserved. `orphan` becomes a root because its parent is missing.
Hints
- A hash map from `span_id` to span node lets you find each parent in O(1) time.
- Create copies of all spans with empty `children` lists first, then do a second pass to attach each span to its parent or classify it as a root.