awesome-everything RU
↑ Back to the climb

Algorithms from zero

Trees: code and trace reading

Crux Read four small tree snippets — a traversal, a buggy BST validator, a recursive height function, and a tree-DP path sum — and predict the output or name the highest-leverage fix.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at middle altitude — in the sky
◷ 14 min

Tree bugs hide in the order of two recursive calls and in the difference between a local check and a global one. Read each snippet, run it in your head, and pick what a careful engineer would conclude or fix first.

Goal

Practise the core reading loop for tree code: predict a traversal’s exact output, spot the off-by-one-subtree bug in a BST validator, reason about the base case in recursive height, and recognise when a tree-DP return value must differ from the answer.

Snippet 1 — traversal order

function walk(node) {
  if (node === null) return;
  walk(node.left);
  console.log(node.value);
  walk(node.right);
}

//        5
//       / \
//      3   8
//     / \   \
//    2   4   9
walk(root);
Quiz

What exact sequence does this print, and what traversal is it?

Snippet 2 — the BST validator bug

function isBST(node) {
  if (node === null) return true;
  if (node.left && node.left.value >= node.value) return false;
  if (node.right && node.right.value <= node.value) return false;
  return isBST(node.left) && isBST(node.right);
}

//        5
//       / \
//      3   8
//         /
//        4      // 4 < 5, but sits in the RIGHT subtree of 5
Quiz

This validator returns true for the tree above, which is NOT a valid BST. What is the bug?

Snippet 3 — recursive height

function height(node) {
  if (node === null) return 0;       // note: returns 0, not -1
  return 1 + Math.max(height(node.left), height(node.right));
}

// single leaf node
console.log(height(leaf));
Quiz

With the null base case returning 0, what does height(leaf) print, and what convention does that imply?

Snippet 4 — tree-DP path sum

function maxPathSum(root) {
  let best = -Infinity;
  function gain(node) {
    if (node === null) return 0;
    const left = Math.max(gain(node.left), 0);   // drop negative branches
    const right = Math.max(gain(node.right), 0);
    best = Math.max(best, node.value + left + right);  // path THROUGH node
    return node.value + Math.max(left, right);          // path the parent can extend
  }
  gain(root);
  return best;
}
Quiz

Why does gain() return node.value + max(left, right) while best is updated with node.value + left + right?

Recap

Reading tree code comes down to a few reflexes: locate the visit line relative to the two recursive calls to name the traversal (and remember in-order on a BST is sorted); never trust a BST validator that only checks parent-against-child — correctness needs a propagated (min, max) bound; read the null base case to know whether height is counted in nodes (return 0) or edges (return -1); and in tree DP, watch for the deliberate gap between what a node returns to its parent (one extendable branch) and what it contributes to the global answer (the full bend through it).

Continue the climb ↑Trees: build a BST toolkit
shortcuts expand
search
K
prev piece
k
next piece
j
cycle tier
t
this menu
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.