PracHub
QuestionsPremiumCoachesLearningGuidesInterview Prep

Quick Overview

This question evaluates competence in binary tree manipulation and combinatorial search, covering promotion-based node deletion, height computation across forest components after root deletion, enumeration of deletion sets with deduplication, pruning strategies, and time/space complexity analysis.

  • Medium
  • Snowflake
  • Coding & Algorithms
  • Software Engineer

Compute height after deletions; enumerate valid delete sets

Company: Snowflake

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: Medium

Interview Round: Technical Screen

Warm-up: You are given a rooted binary tree with unique node ids and a list of ids to delete. When a node is deleted, promote all of its children to become children of the deleted node’s parent (preserving left/right positions when possible; if only one child exists, it occupies the appropriate side). After applying all deletions, compute the number of levels in the resulting tree. State and handle the case where the root is deleted (e.g., produce a forest and return the maximum height across the components) and analyze time/space complexity. Main: With the same promotion rule, you are given a rooted binary tree, an integer n (maximum deletions allowed), and a target height k. Return all unique sets of node ids whose deletion yields a tree whose height is exactly k using at most n deletions. Output each set as a sorted list of ids; avoid duplicates. Describe your search/pruning strategy, correctness argument, and complexity.

Quick Answer: This question evaluates competence in binary tree manipulation and combinatorial search, covering promotion-based node deletion, height computation across forest components after root deletion, enumeration of deletion sets with deduplication, pruning strategies, and time/space complexity analysis.

Part 1: Height After Deletions with Child Promotion

You are given a rooted binary tree with unique positive integer node ids. The tree is represented by a root id and a dictionary mapping each node id to its left and right child ids. A missing child is represented by -1. You are also given a list of node ids to delete. When a node is deleted, it is removed and its children are promoted upward. For purposes of computing height, this is equivalent to contracting deleted nodes: deleted nodes do not count as levels, but their non-deleted descendants may still remain connected to the nearest non-deleted ancestor. If the root is deleted, the result may be a forest; return the maximum height among all forest components. Return the number of levels in the resulting tree or forest. An empty result has height 0.

Constraints

  • 0 <= number of nodes <= 100000
  • Node ids are unique positive integers.
  • root_id is -1 if and only if the tree is empty.
  • Every non-missing child id appears as a key in nodes.
  • The input graph is a valid rooted binary tree with no cycles.
  • delete_ids contains valid node ids from the tree.

Examples

Input: (-1, {}, [])

Expected Output: 0

Explanation: The tree is empty, so the resulting forest is empty.

Input: (10, {10: [-1, -1]}, [10])

Expected Output: 0

Explanation: The only node is deleted, leaving an empty forest.

Input: (1, {1: [2, 3], 2: [4, 5], 3: [-1, 6], 4: [-1, -1], 5: [-1, -1], 6: [-1, -1]}, [2])

Expected Output: 3

Explanation: Deleting node 2 promotes nodes 4 and 5, but the path 1 -> 3 -> 6 still has 3 levels.

Input: (1, {1: [2, 3], 2: [4, 5], 3: [-1, 6], 4: [-1, -1], 5: [-1, -1], 6: [-1, -1]}, [1])

Expected Output: 2

Explanation: Deleting the root creates a forest rooted at promoted children. The tallest component has height 2.

Input: (1, {1: [2, 3], 2: [4, 5], 3: [-1, 6], 4: [-1, -1], 5: [-1, -1], 6: [-1, -1]}, [2, 3])

Expected Output: 2

Explanation: Nodes 2 and 3 are removed, so the deepest remaining paths from node 1 have 2 levels.

Solution

def solution(root_id, nodes, delete_ids):
    deleted = set(delete_ids)

    if root_id == -1:
        return 0

    # Postorder traversal without recursion, so skewed trees are safe.
    heights = {-1: 0}
    stack = [(root_id, False)]

    while stack:
        node, visited = stack.pop()
        if node == -1:
            continue

        if visited:
            left, right = nodes[node]
            best_child_height = max(heights.get(left, 0), heights.get(right, 0))

            if node in deleted:
                # Deleted nodes do not count as a level; their children are promoted.
                heights[node] = best_child_height
            else:
                heights[node] = 1 + best_child_height
        else:
            stack.append((node, True))
            left, right = nodes[node]
            if right != -1:
                stack.append((right, False))
            if left != -1:
                stack.append((left, False))

    return heights[root_id]

Time complexity: O(N + D), where N is the number of nodes and D is the number of ids in delete_ids.. Space complexity: O(N + D), for the height table, traversal stack, and deletion set..

Hints

  1. For height, you do not need to explicitly rebuild the promoted tree.
  2. A deleted node contributes 0 levels but passes upward the maximum height of its children.

Part 2: Enumerate Deletion Sets Producing a Target Height

You are given a rooted binary tree with unique positive integer node ids. The tree uses the same representation as Part 1: each node maps to [left_child_id, right_child_id], and -1 means no child. You are also given max_deletions and target_height. Return every unique set of node ids whose deletion produces a resulting tree/forest of height exactly target_height, using at most max_deletions deletions. The same promotion rule applies: deleting a node removes it, and its children are promoted upward. For height computation, this is equivalent to contracting deleted nodes. If the root is deleted, the result may be a forest, and the height is the maximum component height. Each returned deletion set must be sorted in ascending order. The outer list of deletion sets must also be sorted lexicographically. Do not return duplicates.

Constraints

  • 0 <= number of nodes <= 18
  • 0 <= max_deletions <= number of nodes
  • 0 <= target_height <= number of nodes
  • Node ids are unique positive integers.
  • root_id is -1 if and only if the tree is empty.
  • Every non-missing child id appears as a key in nodes.
  • The input graph is a valid rooted binary tree with no cycles.

Examples

Input: (-1, {}, 3, 0)

Expected Output: [[]]

Explanation: The empty deletion set leaves an empty forest with height 0.

Input: (7, {7: [-1, -1]}, 1, 0)

Expected Output: [[7]]

Explanation: Deleting the only node is the only way to get height 0.

Input: (1, {1: [2, 3], 2: [4, 5], 3: [-1, 6], 4: [-1, -1], 5: [-1, -1], 6: [-1, -1]}, 0, 3)

Expected Output: [[]]

Explanation: No deletions are allowed, and the original tree already has height 3.

Input: (1, {1: [2, 3], 2: [4, 5], 3: [-1, 6], 4: [-1, -1], 5: [-1, -1], 6: [-1, -1]}, 1, 2)

Expected Output: [[1]]

Explanation: With one deletion, only deleting the root reduces the maximum height from 3 to exactly 2.

Input: (1, {1: [2, 3], 2: [4, 5], 3: [-1, 6], 4: [-1, -1], 5: [-1, -1], 6: [-1, -1]}, 2, 2)

Expected Output: [[1], [1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [2, 3], [2, 6]]

Explanation: These are exactly the deletion sets of size at most 2 that hit every original 3-level path while leaving at least one 2-level path.

Solution

def solution(root_id, nodes, max_deletions, target_height):
    from itertools import combinations

    ids = sorted(nodes.keys())
    limit = min(max_deletions, len(ids))

    def compute_height(deleted):
        if root_id == -1:
            return 0

        heights = {-1: 0}
        stack = [(root_id, False)]

        while stack:
            node, visited = stack.pop()
            if node == -1:
                continue

            if visited:
                left, right = nodes[node]
                best_child_height = max(heights.get(left, 0), heights.get(right, 0))

                if node in deleted:
                    heights[node] = best_child_height
                else:
                    heights[node] = 1 + best_child_height
            else:
                stack.append((node, True))
                left, right = nodes[node]
                if right != -1:
                    stack.append((right, False))
                if left != -1:
                    stack.append((left, False))

        return heights[root_id]

    answer = []

    # Generate combinations directly, so each set appears once.
    for size in range(limit + 1):
        for combo in combinations(ids, size):
            deleted = set(combo)
            if compute_height(deleted) == target_height:
                answer.append(list(combo))

    answer.sort()
    return answer

Time complexity: O(M * S + output_size), where M is the number of nodes and S = sum(C(M, i) for i = 0..min(max_deletions, M)) candidate deletion sets.. Space complexity: O(M + output_size), excluding the returned output contents this uses O(M) auxiliary space per height computation..

Hints

  1. Sort node ids first and generate combinations, not permutations, to avoid duplicate deletion sets.
  2. For each candidate set, compute height using the same contracted-node recurrence from Part 1.
Last updated: Jun 16, 2026

Loading coding console...

PracHub

Master your tech interviews with 8,000+ real questions from top companies.

Product

  • Questions
  • Learning Tracks
  • Interview Guides
  • Resources
  • Premium
  • For Universities
  • Student Access

Browse

  • By Company
  • By Role
  • By Category
  • Topic Hubs
  • SQL Questions
  • Compare Platforms
  • Discord Community

Support

  • support@prachub.com
  • (916) 541-4762

Legal

  • Privacy Policy
  • Terms of Service
  • About Us

© 2026 PracHub. All rights reserved.

Related Coding Questions

  • Solve Matrix and Array Distance Problems - Snowflake (medium)
  • Solve Array Distance and Wiki Navigation - Snowflake (medium)
  • Implement Document Predicate APIs - Snowflake (medium)
  • Find Shortest Wiki Click Path - Snowflake (medium)
  • Compute Inherited Role Privileges - Snowflake (hard)