Find root IDs and paths
Company: ZipHQ
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates understanding of graph/tree relationships, identification of root nodes, and path reconstruction from parent references, assessing algorithmic reasoning and data-structure familiarity.
Find Root IDs
Constraints
- 0 <= number of blocks <= 10^5
- Each id is a non-empty string and ids are unique.
- parentId is either null or a string (which may or may not match an existing id).
- Return roots in the order their blocks appear in the input.
Examples
Input: ([{"id": "a", "parentId": None}, {"id": "b", "parentId": "a"}, {"id": "c", "parentId": "b"}],)
Expected Output: ['a']
Explanation: Only 'a' has no parent; 'b' and 'c' chain up to it.
Input: ([{"id": "a", "parentId": None}, {"id": "b", "parentId": None}, {"id": "c", "parentId": "a"}, {"id": "d", "parentId": "b"}],)
Expected Output: ['a', 'b']
Explanation: Two separate trees, so two roots, returned in input order.
Hints
- First collect every block's id into a hash set so you can test 'does this parent exist?' in O(1).
- A block is a root when parentId is null OR parentId is not in that set — handle the dangling-reference case explicitly.
- Preserve input order by iterating the blocks a second time rather than iterating the set.
Path From Root To Target
Constraints
- 0 <= number of blocks <= 10^5
- ids are unique, non-empty strings.
- parentId is null or a string; a dangling parentId marks a root.
- If targetId is not one of the block ids, return an empty list.
- The path is returned root-first, target-last.
Examples
Input: ([{"id": "a", "parentId": None}, {"id": "b", "parentId": "a"}, {"id": "c", "parentId": "b"}], "c")
Expected Output: ['a', 'b', 'c']
Explanation: Walk c -> b -> a, then reverse to root-first order.
Input: ([{"id": "a", "parentId": None}, {"id": "b", "parentId": "a"}, {"id": "c", "parentId": "b"}], "a")
Expected Output: ['a']
Explanation: The target is itself a root, so the path is just [a].
Hints
- Build a map id -> effective parent, normalizing both null and dangling parents to 'no parent' (None).
- Walk upward from the target collecting ids until you hit a node with no parent, then reverse the collected list.
- Guard against cycles with a visited set so a malformed input can't loop forever; also return [] up front when the target isn't present.