Delete and Compact a Forest Stored by Parent Indices
PinterestSoftware Engineer · Technical ScreenLast updated
Implement subtree deletion on a parent-pointer forest array, supporting tombstoning and index compaction with pointer remapping.
Delete and Compact a Forest Stored by Parent Indices
You are given a forest of trees represented as a zero-indexed array parents of length n, where parents[i] indicates the parent node of node i.
In this representation:
- A root node points to itself:
parents[i] == i. - Every tree in the forest is valid (no cycles other than root self-loops).
You are also given an integer target representing the node to delete, and a boolean flag compact.
Deleting a node requires deleting the node itself along with all of its descendants (the entire subtree rooted at target).
Your task is to implement the deletion under two different modes:
-
Tombstoning (
compact = False):- Retain the original array length
n. - Set
parents[i] = -1fortargetand all its descendants. - All surviving nodes must retain their original indices and parent pointers.
- Retain the original array length
-
Compacting (
compact = True):- Completely remove
targetand all its descendants. - Preserve the relative order of surviving nodes.
- Re-index surviving nodes sequentially from
0tok - 1, wherekis the number of survivors. - Rewrite all parent references to match the new indices.
- Ensure surviving roots remain self-referential (
parents[new_i] == new_i).
- Completely remove
Function Signature
def delete_subtree(parents: list[int], target: int, compact: bool = False) -> list[int]:
pass
Examples
Example 1:
Input: parents = [0, 0, 1, 1, 2], target = 1, compact = False
Output: [0, -1, -1, -1, -1]
Explanation:
- Node 0 is a root.
- Node 1 is a child of 0.
- Nodes 2 and 3 are children of 1.
- Node 4 is a child of 2.
The subtree rooted at node 1 contains {1, 2, 3, 4}. Tombstoning marks them as -1.
Example 2:
Input: parents = [0, 0, 2, 2, 3], target = 0, compact = True
Output: [0, 0, 1]
Explanation:
- Subtree rooted at 0 contains {0, 1}.
- Survivors are {2, 3, 4}.
- Re-indexing: old 2 -> new 0, old 3 -> new 1, old 4 -> new 2.
- Old parent pointers: 2 -> 2 (root), 3 -> 2, 4 -> 3.
- Remapped parent pointers: new 0 -> 0 (root), new 1 -> 0, new 2 -> 1.
Constraints
1 <= len(parents) <= 10^50 <= parents[i] < len(parents)0 <= target < len(parents)- The input represents a valid forest where every node eventually leads to a self-referential root.
Hints
Hint 1
Identify all nodes to delete by traversing upward to check if a node's ancestor is target, or by building an adjacency list of children and running BFS/DFS from target.
Hint 2
For the compact mode, build an index mapping old_index -> new_index for all surviving nodes while iterating in ascending order.
Hint 3
Apply the index mapping to both the position of each surviving node and its parent pointer.
Follow-up questions
- How would you handle multiple consecutive deletions without rebuilding the entire forest each time?
- Can you optimize the subtree identification step to O(n) time and O(1) auxiliary space if mutating the input array in place is allowed?
- How would your approach change if the forest could contain invalid cycles or detached subgraphs?
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.