Skip to content
AI360Xpert
Beta
Difficulty: MediumTrees

Count Good Nodes in Binary Tree

Problem in Plain English

Given the root of a binary tree, count the nodes whose value is greater than or equal to every value on the path from the root. The root itself always counts as good.

Problem Statement

A node X in a binary tree is good when no node on the path from the root down to X holds a value greater than X.

Given the root of a binary tree, return the total number of good nodes. The root has no ancestors above it, so it is always good.

Constraints

  • 1 <= number of nodes <= 10^5
  • -10^4 <= Node.val <= 10^4

Examples

Example 1

Input
root = [3,1,4,3,null,1,5]
Output
4

3, the leaf 3, 4, and 5 each match or beat every ancestor above them, while 1 and the second 1 do not.

Example 2

Input
root = [3,3,null,4,2]
Output
3

Both 3 nodes and 4 are good, but 2 sits below a larger 3.

Example 3

Input
root = [1]
Output
1

The root is good by definition.

Example 4

Input
root = [-3,-4,-2]
Output
2

The root -3 is good. The left child -4 is below -3 and fails; the right child -2 exceeds -3 and passes. Starting a maximum at zero would incorrectly reject every node.

Example 5

Input
root = [3,9,4]
Output
3

The root 3 and both children are good: each child only compares with ancestor 3. Visiting 9 first must not raise the threshold for its sibling 4.

Intuition

A good node ties or sets a record along its own root-to-node path. Only its ancestors matter: a larger value in a sibling subtree cannot disqualify it. In Example 1, the leaf 3 below 1 is good because its ancestors are 1 and 3, while the leaf 1 below 4 is not. Checking every ancestor separately repeats shared paths; carrying the path maximum gives each node the whole comparison in one number. Equal values count, and the starting maximum must handle negative values.

Approaches

Path Check Per Node

Solution Details

Reveal Path Check Per Node: intuition, complexity, and code

Hints

Hint 1
Compare a node with its ancestors, not with every value in the tree. The root always qualifies.
Hint 2
The ancestors can be summarized by their maximum value. A node equal to that maximum still qualifies.
Hint 3
Carry the maximum in each pending stack entry and update it before pushing children. Use an explicit stack to handle the maximum valid depth.

Edge Cases

  • A single node is always good, even at value -10000. The public input is nonempty; the snippets additionally return zero for null.
  • An increasing root-to-leaf chain makes every node good; a strictly decreasing chain makes only the root good.
  • An all-equal tree makes every node good, since equality is permitted. This is also the parent-check baseline's quadratic worst case on a chain.
  • Negative values work unchanged when the initial threshold is root.val rather than zero.
  • A large left-subtree value must not disqualify a smaller good node in the right subtree, as root [3,9,4] demonstrates.
  • A 100000-node chain requires iterative traversal in these languages; the optimal stack has only one pending node on that shape.

Common Mistakes and Interview Tips

  • Using one shared maximum across siblings: in [3,9,4], visiting 9 must not make 4 fail.
  • Comparing with strict greater-than when counting good nodes, which rejects legitimate ties.
  • Comparing only with the direct parent: in [5,1,null,3], leaf 3 exceeds parent 1 but fails against ancestor 5.
  • Initializing the maximum to zero, which incorrectly rejects an entirely negative tree.
  • Using recursion without accounting for the 100000-node depth bound; Python, Java and JavaScript may overflow their call stacks.
  • Treating the O(n²) parent-check baseline as suitable for every maximum-size input; equal-valued long chains force every ancestor walk to finish.

Key Takeaway

When a root-path predicate depends only on an aggregate such as maximum, minimum or sum, carry that aggregate with each pending node. Update it locally for children so siblings inherit the same prefix state without sharing later changes.