Count the Number of Good Nodes - Solution & Explanation
Problem Statement
There is an undirected tree with n nodes labeled from 0 to n - 1, and rooted at node 0. You are given a 2D integer array edges of length n - 1, where edges[i] = [ai, bi] indicates that there is an edge between nodes ai and bi in the tree.
A node is good if all the subtrees rooted at its children have the same size.
Return the number of good nodes in the given tree.
A subtree of treeName is a tree consisting of a node in treeName and all of its descendants.
Example 1:
Input: edges = [[0,1],[0,2],[1,3],[1,4],[2,5],[2,6]]
Output: 7
Explanation:
All of the nodes of the given tree are good.
Example 2:
Input: edges = [[0,1],[1,2],[2,3],[3,4],[0,5],[1,6],[2,7],[3,8]]
Output: 6
Explanation:
There are 6 good nodes in the given tree. They are colored in the image above.
Example 3:
Input: edges = [[0,1],[1,2],[1,3],[1,4],[0,5],[5,6],[6,7],[7,8],[0,9],[9,10],[9,12],[10,11]]
Output: 12
Explanation:
All nodes except node 9 are good.
Constraints:
2 <= n <= 105edges.length == n - 1edges[i].length == 20 <= ai, bi < n- The input is generated such that
edgesrepresents a valid tree.
Approach Overview
Problem Overview: You are given an undirected tree with n nodes. A node is considered good if all of its child subtrees have the same size. Leaf nodes are automatically good because they have no children. The task is to count how many nodes satisfy this property.
Approach 1: DFS and Size Calculation (O(n) time, O(n) space)
The most direct strategy uses a single Depth-First Search traversal. Start from the root (usually node 0) and recursively compute the size of each subtree. For every node, iterate through its children and record the subtree size returned by DFS. If all recorded sizes are equal, the node is considered good. The subtree size for the current node is then 1 + sum(childSizes), which propagates upward in the recursion.
This works because DFS naturally processes children before their parent, so each node already knows the size of its descendants. During the DFS step you simply compare the first child subtree size with the rest. If any size differs, mark the node as not good. Each edge and node is visited once, giving O(n) time complexity with O(n) recursion stack and adjacency list storage.
Approach 2: DFS with Precomputed Subtree Sizes (O(n) time, O(n) space)
This variation separates the logic into two passes over the tree. The first DFS computes and stores the subtree size of every node in an array. The second traversal checks each node by iterating through its neighbors and considering only children (excluding the parent). Since subtree sizes are already known, you simply compare them directly without recomputation.
This approach improves code clarity in some languages such as Java or C#, where separating computation and validation can make recursion easier to maintain. The first pass fills a subtreeSize[] array, while the second pass checks whether all child subtree sizes match. The complexity remains O(n) time because each edge is processed a constant number of times, and O(n) space for the adjacency list and stored subtree sizes.
Both approaches rely on representing the input as an adjacency list and traversing it with DFS. The key observation is that subtree sizes fully determine whether a node qualifies as good. Once you know the size of every child subtree, verifying the condition becomes a simple equality check.
Recommended for interviews: The single-pass DFS that calculates subtree sizes while checking equality is the approach most interviewers expect. It demonstrates strong understanding of DFS traversal and recursive tree DP patterns. The two-pass version is still O(n) and easier to reason about, but the single-pass solution shows better algorithmic efficiency and control over recursion.
Approach 1: DFS and Size Calculation
This approach uses Depth First Search (DFS) to traverse the tree and determine the size of each subtree. A node is considered 'good' if all its direct child subtrees are of the same size. We traverse the tree starting at the root, using a recursive helper function to count the size of each subtree and verify the 'good' condition by comparing the sizes of all child subtrees.
This Python solution uses an adjacency list to represent the tree and invokes a DFS from the root node to compute subtree sizes recursively. For each node, we maintain a set of unique subtree sizes for its children. If the set contains one or zero elements, it implies all the subtrees have the same size, marking the node as good.
Complexity
Time Complexity: O(n), where n is the number of nodes, since we traverse each node once.
Space Complexity: O(n), for the adjacency list and the recursion stack.
Approach 2: DFS with Precomputed Subtree Sizes
In this approach, we first precompute the size of each subtree using DFS before validating the 'good' condition. This helps in making the second DFS for condition checking efficient by using already computed subtree sizes.
This Java solution separates the process into two main DFS traversals. The first DFS calculates the size of each subtree for all nodes. The second DFS checks the 'good' condition using the precomputed sizes, adding to the count if the condition is met.
Complexity
Time Complexity: O(n), as we traverse the tree nodes twice, once for computing sizes and another for condition checking.
Space Complexity: O(n), required for the adjacency list, size array, and recursion stack.
Approach 3: DFS
First, we construct the adjacency list g of the tree based on the given edges edges, where g[a] represents all the neighboring nodes of node a.
Next, we design a function dfs(a, fa) to calculate the number of nodes in the subtree rooted at node a and to accumulate the count of good nodes. Here, fa represents the parent node of node a.
The execution process of the function dfs(a, fa) is as follows:
- Initialize variables
pre = -1,cnt = 1,ok = 1, representing the number of nodes in a subtree of nodea, the total number of nodes in all subtrees of nodea, and whether nodeais a good node, respectively. - Traverse all neighboring nodes
bof nodea. Ifbis not equal tofa, recursively calldfs(b, a), with the return value beingcur, and addcurtocnt. Ifpre < 0, assigncurtopre; otherwise, ifpreis not equal tocur, it means the number of nodes in different subtrees of nodeais different, and setokto0. - Finally, add
okto the answer and returncnt.
In the main function, we call dfs(0, -1) and return the final answer.
The time complexity is O(n), and the space complexity is O(n). Here, n represents the number of nodes.
Code
Python
Java
C++
Go
TypeScript
Complexity Comparison
| Approach | Complexity |
|---|---|
| DFS and Size Calculation | Time Complexity: O(n), where n is the number of nodes, since we traverse each node once. Space Complexity: O(n), for the adjacency list and the recursion stack. |
| DFS with Precomputed Subtree Sizes | Time Complexity: O(n), as we traverse the tree nodes twice, once for computing sizes and another for condition checking. Space Complexity: O(n), required for the adjacency list, size array, and recursion stack. |
| DFS | — |
Detailed Complexity Analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| DFS with Subtree Size Calculation | O(n) | O(n) | Best general solution. Computes subtree sizes and validates good nodes in a single DFS traversal. |
| DFS with Precomputed Subtree Sizes | O(n) | O(n) | Useful when separating computation and validation logic for clarity, especially in strongly typed languages. |
Video Solution
3249 Count the Number of Good Nodes || How to 🤔 in Interview || Build Graph + DFS || Math • Ayush Rao • 2,430 views views
Watch 6 more video solutions →Frequently Asked Questions
Is Count the Number of Good Nodes easy or hard?
Count the Number of Good Nodes Python/Java solution
How to solve Count the Number of Good Nodes in O(n)?
What is the best approach for Count the Number of Good Nodes?
Is Count the Number of Good Nodes asked at Google/Amazon/Meta?
What data structure is used in Count the Number of Good Nodes?
What is the time complexity of Count the Number of Good Nodes?
Ready to solve this problem?
Practice Count the Number of Good Nodes with our built-in code editor and test cases.
Practice on FleetCodeProblem Info
Table of Contents
Practice this problem
Open in Editor