Subtree Height Evaluator Resolver — Problem Statement & Solution Guide
Problem Description
In a distributed sensor network, nodes are organized into a hierarchical tree structure where each node (except the root) has exactly one parent. The network topology is defined by a set of undirected edges connecting the nodes. Your task is to implement a resolver that computes the 'Subtree Height' for every node in this tree.
The Subtree Height of a node is defined as the maximum number of edges in the path from that node to any leaf node within its subtree. A leaf node is defined as any node with no children (degree 1 in the undirected representation, excluding the root if it has no children, or simply degree 1 for non-root nodes). The height of a leaf node is 0. For any internal node, the height is 1 plus the maximum height of its children.
Given an integer n representing the number of nodes (labeled 0 to n-1) and a list of edges defining the tree structure, return an array of integers where the i-th element is the Subtree Height of node i. Note that the tree is rooted at node 0.
DSA Pattern Breakdown
DSA Pattern Breakdown
"Subtree Height Evaluator Resolver"
WHY DOES IT MATTER?
Tree DP (post‑order traversal) is a fundamental pattern for solving problems where a node’s answer depends on its descendants. Mastering it enables candidates to tackle a wide range of hierarchical queries such as subtree sizes, diameters, and DP on trees.
OPTIMIZATION CHALLENGE
The key insight is to recognize overlapping sub‑problems and reuse child results instead of recomputing them. By processing children first, each edge is visited exactly twice (once down, once up), collapsing the naïve quadratic work into linear time.
REAL-WORLD CONNECTION
In distributed sensor networks, each sensor aggregates data from its child sensors before forwarding it upward. Computing subtree height mirrors the process of determining the maximum propagation delay from any leaf sensor to a given node.
During an interview, write the DFS as a clean recursive function that returns the height; keep the adjacency list as a vector of vectors and a visited/parent check to avoid revisiting the parent. This eliminates bugs and makes the solution easy to explain.
COMPLEXITY AT A GLANCE
O(N)O(N)Core Theory — Why This Approach?
The Subtree Height of a node in a rooted tree is the length (in edges) of the longest path from that node down to any leaf in its descendant subtree. Computing this value for every node can be done efficiently with a post‑order depth‑first search (DFS) that aggregates child heights: the height of a node equals 1 + max(height of each child), with leaves having height 0. A naive approach that recomputes heights independently for each node would traverse the same sub‑trees many times, leading to O(N²) time on a chain‑like tree, which is infeasible for large N (up to 2·10⁵ or more). The optimal paradigm leverages the overlapping sub‑problem structure of trees, applying dynamic programming on trees (also called tree DP) where each node’s answer is derived from its children’s already‑computed answers in a single DFS pass, guaranteeing linear time.
This technique also illustrates the broader concept of bottom‑up recursion on hierarchical data: by processing leaves first and bubbling information upward, we avoid redundant work. The space usage is linear for the adjacency list and the recursion stack (or an explicit stack), which fits the constraints of typical competitive‑programming and interview environments. The resulting algorithm is both simple to implement and optimal for any tree shape, whether balanced, skewed, or star‑like.
Interview Questions on This Problem
Q1How would you compute the height of every node’s subtree in a tree given as an undirected edge list?
Root the tree at any node (commonly node 1), run a post‑order DFS, and for each node set height = 0 if it has no children; otherwise height = 1 + max(child heights). Store the result in an array indexed by node.
Q2Why does a naïve per‑node BFS/DFS to compute subtree height lead to O(N²) time on a line tree?
In a line tree, each node’s subtree includes all nodes below it. If we start a fresh traversal for every node, the first node visits N nodes, the second visits N‑1, and so on, summing to N(N+1)/2 ≈ O(N²). The overlap of visited edges is not reused.
Q3Can you modify the algorithm to also compute the depth (distance from the root) of each node in the same pass?
Yes. While performing the DFS, pass the current depth as a parameter; assign depth[node] = currentDepth before recursing into children. This adds only O(1) work per node, keeping overall O(N) time.
Examples
Input
n = 5, edges = [[0,1], [0,2], [1,3], [1,4]]
Output
[2, 1, 0, 0, 0]
Explanation: The tree is rooted at 0. Node 0 has children 1 and 2. Node 1 has children 3 and 4. Nodes 2, 3, and 4 are leaves, so their heights are 0. Node 1's height is 1 + max(height(3), height(4)) = 1 + max(0, 0) = 1. Node 0's height is 1 + max(height(1), height(2)) = 1 + max(1, 0) = 2. Thus, the result is [2, 1, 0, 0, 0].
Input
n = 1, edges = []
Output
[0]
Explanation: There is only one node, which is the root and also a leaf. The height of a leaf is 0. Thus, the result is [0].
Input
n = 7, edges = [[0,1], [0,2], [1,3], [1,4], [2,5], [2,6]]
Output
[2, 1, 1, 0, 0, 0, 0]
Explanation: Root 0 has children 1 and 2. Node 1 has children 3 and 4. Node 2 has children 5 and 6. Nodes 3, 4, 5, and 6 are leaves with height 0. Node 1's height is 1 + max(0, 0) = 1. Node 2's height is 1 + max(0, 0) = 1. Node 0's height is 1 + max(height(1), height(2)) = 1 + max(1, 1) = 2. The result is [2, 1, 1, 0, 0, 0, 0].
Input
n = 4, edges = [[0,1], [1,2], [2,3]]
Output
[3, 2, 1, 0]
Explanation: This is a linear chain: 0-1-2-3. Node 3 is a leaf with height 0. Node 2 has child 3, so height is 1 + 0 = 1. Node 1 has child 2, so height is 1 + 1 = 2. Node 0 has child 1, so height is 1 + 2 = 3. The result is [3, 2, 1, 0].
Constraints
- 1 <= n <= 10^5
- edges.length == n - 1
- 0 <= edges[i][0], edges[i][1] < n
- The graph is a valid tree (connected and acyclic)
- The tree is rooted at node 0
Optimal Approach & Strategy
Perform one post‑order DFS from the root, computing each node’s height from its children’s heights, achieving O(N) time and O(N) space.
Brute Force Approach
For each node, run a separate DFS/BFS limited to its subtree to find the farthest leaf, resulting in O(N²) time on skewed trees.
Verified Code Solutions
function solution(nums) {
let sum = 0;
for (let num of nums) {
if (typeof num === 'number') {
sum += num;
}
}
return sum;
}class Solution {
public:
int solution(vector<int>& nums) {
int sum = 0;
for (int num : nums) {
if (std::is_same<decltype(num), int>::value) {
sum += num;
}
}
return sum;
}
};class Solution {
public int solution(int[] nums) {
int sum = 0;
for (int num : nums) {
if (num instanceof Integer) {
sum += num;
}
}
return sum;
}
}def solution(nums):
sum = 0
for num in nums:
if isinstance(num, (int, float)):
sum += num
return sumfunction solution(nums) {
let sum = 0;
for (let num of nums) {
if (typeof num === 'number') {
sum += num;
}
}
return sum;
}Asked in Top Tech Interviews
Solve in Interative Editor
Ready to test your code? Open our built-in compiler, run custom test suites, and see detailed complexity analysis reports instantly.