medium Count Good Nodes in Binary Tree
Problem Statement
Given a binary tree root, return the number of good nodes in the binary tree.
A node is considered good if in the path from the root to this node, there are no nodes with a value greater than this node's value.
Examples
Example 1
- Input: root =
[3, 1, 3, 3, null, 1, 5]
- Expected Output:
4 - Explanation:
- Root node (3) is always good.
- Node
5is also a good node. - Both nodes
3are good.
Example 2
- Input: root =
[2, 3, 4, 1, null, null, 5]
- Expected Output:
4 - Explanation:
- Nodes
2,3,4, and5are good. - The node with value
1is not good because3is greater and comes before it.
- Nodes
Example 3
- Input: root =
[10, 8, 15, 7, 9, 12, 20]
- Expected Output:
3 - Explanation:
- Nodes
10,15, and20are good.
- Nodes
Constraints:
- The number of nodes in the binary tree is in the range [1, 10^5].
- Each node's value is between [-104, 10^4].
Try it yourself
Try solving this question here:
✅ Solution Count Good Nodes in Binary Tree
Problem Statement
Given a binary tree root, return the number of good nodes in the binary tree.
A node is considered good if in the path from the root to this node, there are no nodes with a value greater than this node's value.
Examples
Example 1
- Input: root =
[3, 1, 3, 3, null, 1, 5]
- Expected Output:
4 - Explanation:
- Root node (3) is always good.
- Node
5is also a good node. - Both nodes
3are good.
Example 2
- Input: root =
[2, 3, 4, 1, null, null, 5]
- Expected Output:
4 - Explanation:
- Nodes
2,3,4, and5are good. - The node with value
1is not good because3is greater and comes before it.
- Nodes
Example 3
- Input: root =
[10, 8, 15, 7, 9, 12, 20]
- Expected Output:
3 - Explanation:
- Nodes
10,15, and20are good.
- Nodes
Constraints:
- The number of nodes in the binary tree is in the range [1, 10^5].
- Each node's value is between [-104, 10^4].
Solution
To solve this problem, we will use Depth-First Search (DFS) traversal. The idea is to traverse the tree starting from the root and keep track of the maximum value encountered on the path from the root to the current node. If the current node's value is greater than or equal to the maximum value seen so far, it is a good node. We then update the maximum value and continue to traverse the tree.
This approach works because it ensures that we only count a node as good if all nodes on the path from the root to that node have values less than or equal to the current node's value. By updating the maximum value dynamically as we traverse, we can efficiently determine if a node is good.
Step-by-step Algorithm
-
Initialization:
- Start with the root node of the tree.
-
Define Helper Function (DFS):
- Define a helper function
dfs(node, maxVal)to perform depth-first search (DFS) on the tree. Initially, consider root node's value as amaxVal. - If the current
nodeisnull, return 0 because there are no nodes to consider.
- Define a helper function
-
Check Good Node:
- Check if the value of the current
nodeis greater than or equal tomaxVal. - If it is, this node is a good node. Initialize a variable
countto 1. - Otherwise, set
countto 0.
- Check if the value of the current
-
Update Maximum Value:
- Update
maxValto be the maximum of the currentnode's value and the previousmaxVal.
- Update
-
Recur for Subtrees:
- Recursively call
dfsfor the left child of the current node with the updatedmaxValand add the result tocount. - Recursively call
dfsfor the right child of the current node with the updatedmaxValand add the result tocount.
- Recursively call
-
Return Count:
- Return the total count of good nodes found in the current subtree.
Algorithm Walkthrough
-
Initialization:
- Start at the root node with value 2.
- Initialize
maxVal= 2.
-
Step-by-Step DFS Traversal:
-
At Node 2:
maxVal= 2- 2 >= 2, so node 2 is a good node.
- Count = 1
- Update
maxVal= max(2, 2) = 2 - Recur for left child (Node 3).
-
At Node 3:
maxVal= 2- 3 >= 2, so node 3 is a good node.
- Count = 1
- Update
maxVal= max(2, 3) = 3 - Recur for left child (Node 1).
-
At Node 1:
-
maxVal= 3 -
1 < 3, so node 1 is not a good node.
-
Count = 0
-
maxValremains 3 -
Recur for left and right children (both are null), so return 0 for both.
-
Total count from Node 1's subtree: 0
-
-
Back at Node 3:
- Count from left subtree (Node 1) = 0
- Recur for right child (null), so return 0.
- Total count from Node 3's subtree: 1 (Node 3 itself)
-
Back at Node 2:
- Count from left subtree (Node 3) = 1
- Recur for right child (Node 4).
-
At Node 4:
maxVal= 2- 4 >= 2, so node 4 is a good node.
- Count = 1
- Update
maxVal= max(2, 4) = 4 - Recur for left child (null), so return 0.
- Recur for right child (Node 5).
-
At Node 5:
-
maxVal= 4 -
5 >= 4, so node 5 is a good node.
-
Count = 1
-
Update
maxVal= max(4, 5) = 5 -
Recur for left and right children (both are null), so return 0 for both.
-
Total count from Node 5's subtree: 1
-
-
Back at Node 4:
- Count from right subtree (Node 5) = 1
- Total count from Node 4's subtree: 2 (Nodes 4 and 5)
-
Back at Node 2:
- Count from right subtree (Node 4) = 2
- Total count from Node 2's subtree: 4 (Nodes 2, 3, 4, 5)
-
-
Final Count:
- The total count of good nodes in the tree is 4.
Code
// class TreeNode {
// int val;
// TreeNode left;
// TreeNode right;
// TreeNode(int x) { val = x; }
// TreeNode(int x, TreeNode left, TreeNode right) {
// val = x;
// this.left = left;
// this.right = right;
// }
// }
class Solution {
// Method to count good nodes
public int goodNodes(TreeNode root) {
return dfs(root, root.val);
}
// Helper method to perform DFS
private int dfs(TreeNode node, int maxVal) {
if (node == null) return 0;
int count = node.val >= maxVal ? 1 : 0; // Check if current node is good
maxVal = Math.max(maxVal, node.val); // Update max value on this path
count += dfs(node.left, maxVal); // Recur for left child
count += dfs(node.right, maxVal); // Recur for right child
return count; // Return total count of good nodes
}
public static void main(String[] args) {
Solution sol = new Solution();
TreeNode root1 = new TreeNode(
3,
new TreeNode(1, new TreeNode(3), null),
new TreeNode(4, new TreeNode(1), new TreeNode(5))
);
System.out.println(sol.goodNodes(root1)); // Expected output: 4
TreeNode root2 = new TreeNode(
2,
new TreeNode(3, new TreeNode(1), null),
new TreeNode(4, null, new TreeNode(5))
);
System.out.println(sol.goodNodes(root2)); // Expected output: 4
TreeNode root3 = new TreeNode(
10,
new TreeNode(8, new TreeNode(7), new TreeNode(9)),
new TreeNode(15, new TreeNode(12), new TreeNode(20))
);
System.out.println(sol.goodNodes(root3)); // Expected output: 3
}
}
Complexity Analysis
Time Complexity
The time complexity of this algorithm is
Space Complexity
The space complexity is
🤖 Don't fully get this? Learn it with Claude
Stuck on Count Good Nodes in Binary Tree? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.
Progressively stronger hints — you still solve it.
I'm working on the problem **Count Good Nodes in Binary Tree** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
See the technique, not just code.
Explain the optimal approach to **Count Good Nodes in Binary Tree** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Catch bugs, edge cases, sub-optimality.
I'll paste my solution to **Count Good Nodes in Binary Tree**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
Lock in recognition with look-alikes.
Give me 2 problems that use the SAME underlying pattern as **Count Good Nodes in Binary Tree**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.