InterviewPrepKit

Home / Coding / Trees

Count Good Nodes in Binary Tree

medium Original ↗
Solving tips
  • Recognize the root-to-node path property: goodness depends only on ONE number, the maximum value seen so far along the path from the root.
  • Thread path_max down a DFS as a parameter; a node is good iff node.val >= path_max, then recurse into children with max(path_max, node.val). This is O(n) time, O(h) space.
  • Pitfall: use >= not > — a node tying the running max is still good.
  • Seed the traversal with root.val or float('-inf'), never 0, since values can be negative; and pass the OLD max to children before updating.

Problem

Given the root of a binary tree, call a node good if no node on the path from the root down to it has a value strictly greater than its own value (i.e., the node is greater than or equal to every ancestor on its root path, itself included). Count the good nodes.

The root is always good — there’s nothing above it to beat it.

Examples

Example 1

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

            3
          /   \
         1     4
        /     / \
       3     1   5

Output: 4

Good nodes: 3 (root), 4 (path max so far is 3), 5 (path max 4), and the leaf 3 (path 3→1→3, max 3, and 3 >= 3). The 1s are beaten by the root’s 3.

Example 2

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

            3
           /
          3
         / \
        4   2
Output: 3

Good: root 3, the second 3 (ties count), and 4. The 2 loses to the 3s above it.

Example 3

Input:  root = [7]
Output: 1

A lone root is always good.

Constraints

  • Number of nodes is in [1, 10^5].
  • -10^4 <= Node.val <= 10^4
  • Expected complexity: O(n) time — a single traversal; O(h) extra space.

Think about it first

Hint 1 "No ancestor is greater than me" only depends on one number about the ancestors. Which number?
Hint 2 If you know the maximum value seen along the path so far, deciding whether the current node is good is one comparison. How does that maximum update as you step to a child?
Hint 3 DFS carrying `path_max` as a parameter: count the node if `node.val >= path_max`, then recurse into children with `max(path_max, node.val)`. An explicit stack of `(node, path_max)` pairs does the same iteratively.
Your workspace Not runnable by design — this is your interview scratchpad. Saved on this device.