3. Depth vs height (down vs up)¶
Two measurements that point in opposite directions¶
- Depth of a node = number of edges from the root down to it. The root has depth 0.
- Height of a node = number of edges from it down to its deepest leaf. Leaves have height 0.
Click any node. The pink path goes up to the root (depth). The orange path goes down to the farthest leaf (height).
Now press Label all depths, then Label all heights. Depths count up as you go down the tree; heights count up as you go up the tree. They're mirror images, and they're computed in opposite directions.
Who has the information?¶
Ask: to know this number for node X, whose information do I need?
- Depth of X depends only on X's ancestors (how many there are). X's parent knows its own depth, so it can tell X: "you're one deeper than me." → pass it down as a parameter.
- Height of X depends only on X's descendants. Nobody above X knows anything about X's subtree. X has to ask its children and wait. → get it back as a return value.
Watch when the numbers appear¶
Switch between the two problems below and press ▶ Play on each. Don't look at the values, look at the timing:
- Depth: a node's badge appears the moment it's called, before any of its children are visited. The numbers go down with the calls.
- Height: a node's badge appears only when it returns, after both children have answered. The numbers come back up with the returns. The root is the last to know.
Also look at the call stack for depth: each frame carries depth in its signature, e.g. label_depth(D, 2). The information travels in the arguments. For height, the frames carry left_h and right_h: the information comes back in return values.
"Maximum depth" is the height of the root¶
This one causes real confusion, because LeetCode 104 is called "Maximum Depth of Binary Tree" and the standard solution is the height function.
It's not a contradiction: the deepest node's depth equals the root's height (both are the length of the longest root-to-leaf path). You can compute that number either way:
Both are O(n) and both are correct. The bottom-up one is shorter because the question "how tall is the tree below me?" is naturally a bottom-up question. The top-down one needs a shared best variable because no single call knows the final answer.
Side by side¶
| Depth | Height | |
|---|---|---|
| Measures | edges up to the root | edges down to the deepest leaf |
| Root | 0 | the tree's height |
| Leaves | vary | 0 |
| Depends on | ancestors | descendants |
| Recursion direction | top-down | bottom-up |
| Information travels in | parameters | return values |
| Known at | the call (pre-order) | the return (post-order) |
| Base case does | nothing / stops | returns -1 (or 0) |
Check yourself¶
Two siblings always have the same ___. (depth or height?)
Depth: they have the same parent, so the same ancestors. Their heights can be completely different.
A node's height changes if you add a node somewhere. Where?
Only if the new node is in its subtree (below it). A node's depth changes only if something changes above it.
You need 'for every node, the sum of values on the path from the root to it'. Top-down or bottom-up?
Top-down: it depends on ancestors. Pass running_sum + node.val down as a parameter.
You need 'for every node, the number of nodes in its subtree'. Top-down or bottom-up?
Bottom-up: it depends on descendants. Return 1 + L + R.