Minimum Prunes to Bring a Filesystem Tree's Depth Under a Limit
SnowflakeSoftware Engineer · Technical ScreenLast updated
Given a directory tree where deleting a node reattaches its children to its own parent, find the minimum number of deletions needed to bring the deepest root-to-leaf path down to a given limit. Tests a budget-passing tree DP where deleting a node changes how much depth its children inherit.
A filesystem snapshot is represented as n directories numbered 0 to n - 1, where directory 0 is the root and every other directory has exactly one parent directory, with any number of subdirectories of its own. Deleting a directory does not delete its contents: every subdirectory it contained is reattached directly under its own parent directory. Deleting the directory whose parent was itself already deleted simply continues the chain — a subdirectory always ends up directly under the nearest surviving ancestor directory.
Given a maximum allowed nesting depth k, return the fewest directory deletions needed so that the deepest remaining path from the root is at most k directories long. The root can never be deleted.
Function Signature
def min_deletions_for_max_depth(parent: list[int], k: int) -> int:
parent[i] is the index of directory i's parent, and parent[0] == -1.
Rules
- The depth of a path is the count of directories on it, root included; a snapshot consisting of the root alone has depth
1. - The root (directory
0) is never a candidate for deletion. Every other directory may be deleted. - Return only the count of deletions, not which directories to delete. If the deepest path is already at most
k, the answer is0. - A solution always exists, since deleting every non-root directory leaves a snapshot of depth
1.
Constraints
1 <= len(parent) <= 10^5parent[0] == -1; for everyi >= 1,0 <= parent[i] < len(parent),parent[i] != i, and repeatedly following parents from any directory eventually reaches directory0— the input is guaranteed to form a single valid tree. A directory's parent index is not required to be smaller than its own index.1 <= k <= len(parent)- The snapshot may be a single unbranching chain of up to
10^5directories.
Example 1
parent = [-1, 0, 0, 0, 1, 4, 5, 2], k = 3
Output: 2
Edges: 0->1, 0->2, 0->3, 1->4, 4->5, 5->6, 2->7. The deepest path is 0 -> 1 -> 4 -> 5 -> 6, 5 directories long. Deleting directory 4 reattaches 5 directly under 1, giving the path 0 -> 1 -> 5 -> 6 (4 directories) — still too deep. Deleting directory 5 as well reattaches 6 directly under 1, giving 0 -> 1 -> 6, 3 directories, which satisfies k = 3. No single deletion can bring this chain down to 3, so 2 is minimal.
Example 2
parent = [-1, 0, 1, 2, 3, 4], k = 3
Output: 3
The snapshot is one unbranching chain of 6 directories. Every deletion shortens the remaining chain by exactly one directory, so reaching depth 3 from depth 6 takes exactly 3 deletions.
Example 3
parent = [-1, 0, 1, 2, 0, 4, 5], k = 3
Output: 2
Two chains of depth 4 hang off the root and share nothing but the root itself (0 -> 1 -> 2 -> 3 and 0 -> 4 -> 5 -> 6). A single deletion can only shorten one of the two chains, so each needs its own deletion to come down to depth 3, for a total of 2.
Hints
Hint 1
Work out, for a single unbranching chain, exactly how much one deletion shortens the deepest remaining path by — that's the building block for the general case.
Hint 2
Think recursively: if you decide a directory stays, how much depth 'budget' does that leave for everything underneath it? If you decide to delete it, what budget do ITS children inherit instead?
Hint 3
Define a function over (directory, remaining depth budget) that returns the minimum deletions needed within that directory's contents, assuming the directory itself survives — then handle a child either by keeping it (consumes one unit of budget) or deleting it (its own children inherit the same budget the child would have received).
Hint 4
Watch the boundary case where the remaining budget hits zero: a directory that's still present can never satisfy a budget of zero on its own, since its own existence always counts as at least one level.
Follow-up questions
- How would you convert this recursive solution into an explicit iterative stack to safely handle a chain of 10^5 directories without hitting a recursion limit?
- How would the long path decomposition optimization work in more detail, and why does merging into the heaviest child's array bound the total work at O(n log n)?
- How would you modify the algorithm to also return which directories to delete, not just the count?
- What changes if, instead of a single global k, each directory had its own maximum allowed depth from the root?
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.