Shubham Sourabhthe room · director's cutplain résumé
Room 04 · The Grind — Trees

Count Good Nodes In Binary Tree

MEDIUM✓ CHIP-TIMEDLC #1448 — FULL STATEMENT

The briefingthe full drill, in my own words

The drill: Count the nodes that are the biggest value seen anywhere on their own root-to-node path — ties count too, only a strictly bigger ancestor disqualifies you.

A binary tree arrives, and each node needs to be judged by everything sitting above it. Walking from the root down to any single node traces a path, and that node is "good" exactly when its own value is at least as large as every value that appeared earlier on that path.

Ties work in the node's favor — matching the running maximum still counts as good, and only a strictly larger ancestor knocks a node out. The root itself always qualifies, since no ancestor exists above it to beat.

The task is to tally how many nodes across the whole tree earn that label and hand back the single count.

  • tree sizes range from a single node up to a few thousand
  • node values can be negative, zero, or positive
  • ties with the running maximum count as good
  • only strictly larger ancestors disqualify a node
  • the root is always good by default
EX 01
root = []
→ 0
empty tree
EX 02
root = [1]
→ 1
single node
EX 03
root = [3, 1, 4, 3, null, 1, 5]
→ 4
mixed ancestry

The hintstake only what you need

HINT 1 THE NUDGE

Each node's status depends only on the values strictly above it — the one number worth carrying downward is the running maximum of the path so far.

HINT 2 THE STRUCTURE

The root is always good, trivially — nothing has beaten it yet. What single number do you need to hand each child before recursing?

HINT 3 ONE STEP FROM THE ANSWER

DFS(node, pathMax): count 1 if node.val >= pathMax, then recurse into both children with max(pathMax, node.val).

Coach's boardthe pattern, step by step

THE RUNNING MAXPATTERN · CARRY THE RUNNING MAXroot = [3, 1, 4, 3, null, 1, 5]
STEP 1

Carry the running max of the path from the root downward — a node is good when it ties or beats every ancestor above it.

STEP 1 / 8 · ← → WORK TOO

The splitstwo paces, two languages

grind/count-good-nodes-in-binary-tree.py — RACE PACE
LANG ▸
PACE ▸
class Solution:
    def goodNodes(self, root: TreeNode) -> int:
        def dfs(node: Optional[TreeNode], path_max: float) -> int:
            if not node:
                return 0
            count = 1 if node.val >= path_max else 0
            new_max = max(path_max, node.val)
            return count + dfs(node.left, new_max) + dfs(node.right, new_max)

        return dfs(root, float("-inf"))
TIME O(N)SPACE O(H)PYTHON · RACE PACE · 10 LN

✓ CHIP-TIMEDALL 4 SOLUTIONS RAN GREEN AGAINST SELF-AUTHORED CASES IN CI · JDK 21 · CPYTHON 3.12 · NOTHING PUBLISHES RED