Binary Trees

Last modified: July 21, 2026

1. What is a Binary Tree?

A binary tree is a hierarchical data structure where each node has at most two children, referred to as the left child and the right child.

        1          ← Root
       / \
      2   3        ← Internal nodes
     / \    \
    4   5    6     ← Leaf nodes (no children)

Every node contains:

  • A value/data
  • A pointer/reference to the left child (or None)
  • A pointer/reference to the right child (or None)
class Node:
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None

2. Terminology

TermMeaning
RootThe topmost node (no parent)
LeafA node with no children
Internal nodeAny node with at least one child
Parent / ChildDirect ancestor / descendant
SiblingsNodes sharing the same parent
Depth of a nodeNumber of edges from the root to that node (root has depth 0)
Height of a nodeNumber of edges on the longest path from that node to a leaf
Height of treeHeight of the root node
LevelAll nodes at the same depth (root is level 0 or 1 depending on convention)
SubtreeA node and all its descendants
Ancestor / DescendantAny node on the path to the root / any node reachable going downward

Depth vs Height: Depth is measured top-down (from root). Height is measured bottom-up (from leaves). A leaf node has height 0.


3. Types of Binary Trees

3.1 Full Binary Tree

Every node has either 0 or 2 children β€” never just one.

      1
     / \
    2   3
   / \
  4   5

Property: If there are n internal nodes, there are n+1 leaf nodes.


3.2 Complete Binary Tree

All levels are fully filled except possibly the last, and the last level is filled from left to right.

      1
     / \
    2   3
   / \ /
  4  5 6

Used in: Heaps (array representation works because no gaps exist).


3.3 Perfect Binary Tree

All internal nodes have exactly 2 children and all leaves are at the same level.

        1
       / \
      2   3
     / \ / \
    4  5 6  7

Properties:

  • Height h β†’ exactly 2^(h+1) - 1 total nodes
  • Exactly 2^h leaf nodes
  • A perfect binary tree is both full and complete

3.4 Balanced Binary Tree

The height difference between left and right subtrees of every node is at most 1.

Height of a balanced tree with n nodes: O(log n)

Examples: AVL tree, Red-Black tree.

An unbalanced tree (e.g. a skewed tree) degrades to O(n) for search/insert β€” the BST worst case.


3.5 Degenerate / Skewed Tree

Every internal node has only one child. Essentially a linked list.

1
 \
  2
   \
    3
     \
      4

Height = n-1 β†’ all operations O(n). The worst case for BSTs when inserting sorted data.


3.6 Binary Search Tree (BST)

A binary tree with the ordering property:

  • Left subtree contains only nodes with values less than the parent.
  • Right subtree contains only nodes with values greater than the parent.
  • This holds recursively for every node.
      5
     / \
    3   7
   / \ / \
  2  4 6  8

Operations: Search, Insert, Delete β€” all O(log n) average, O(n) worst case.


4. Key Properties

Node Count

Tree TypeMax Nodes at Level lTotal Nodes (height h)
Any binary tree2^l2^(h+1) - 1 (if perfect)
Perfect BT2^l2^(h+1) - 1
  • Minimum nodes for height h: h + 1 (skewed tree)
  • Maximum nodes for height h: 2^(h+1) - 1 (perfect tree)

Height

  • Minimum height for n nodes: ⌊logβ‚‚(n)βŒ‹
  • Maximum height for n nodes: n - 1 (skewed)

Leaf Nodes in a Full Binary Tree

If a full binary tree has L leaves, it has exactly L - 1 internal nodes, and 2L - 1 total nodes.


5. Tree Traversals

Traversal = visiting every node exactly once in a specific order.

5.1 Inorder (Left β†’ Root β†’ Right)

def inorder(root):
    if root:
        inorder(root.left)
        print(root.val)
        inorder(root.right)

Key use: Inorder traversal of a BST gives elements in sorted ascending order.


5.2 Preorder (Root β†’ Left β†’ Right)

def preorder(root):
    if root:
        print(root.val)
        preorder(root.left)
        preorder(root.right)

Key use: Used to serialize/copy a tree. The root always appears first.


5.3 Postorder (Left β†’ Right β†’ Root)

def postorder(root):
    if root:
        postorder(root.left)
        postorder(root.right)
        print(root.val)

Key use: Used to delete a tree (process children before parent) or evaluate expression trees.


5.4 Level Order (BFS)

Visit nodes level by level, left to right. Uses a queue.

from collections import deque

def level_order(root):
    if not root:
        return
    q = deque([root])
    while q:
        node = q.popleft()
        print(node.val)
        if node.left:  q.append(node.left)
        if node.right: q.append(node.right)

Key use: Finding shortest path, checking if tree is complete, printing level-wise.


Traversal Summary

TraversalOrderCommon Use
InorderL β†’ Root β†’ RSorted output from BST
PreorderRoot β†’ L β†’ RTree serialization, copy
PostorderL β†’ R β†’ RootDeletion, expression eval
Level OrderLevel by levelBFS problems, shortest path

6. Important Recursive Patterns

Most binary tree problems reduce to a few recurring recursive patterns.

Height of a tree

def height(root):
    if not root:
        return -1  # or 0 depending on convention
    return 1 + max(height(root.left), height(root.right))

Count nodes

def count(root):
    if not root:
        return 0
    return 1 + count(root.left) + count(root.right)

Check if two trees are identical

def is_same(p, q):
    if not p and not q: return True
    if not p or not q:  return False
    return p.val == q.val and is_same(p.left, q.left) and is_same(p.right, q.right)

Diameter of a tree

The diameter is the longest path between any two nodes (may or may not pass through root).

def diameter(root):
    res = [0]
    def height(node):
        if not node: return 0
        l, r = height(node.left), height(node.right)
        res[0] = max(res[0], l + r)
        return 1 + max(l, r)
    height(root)
    return res[0]

7. Tree Reconstruction

From Inorder + Preorder

  • First element of preorder = root.
  • Find root in inorder β†’ elements to its left form the left subtree, right form the right subtree.
  • Recurse.

From Inorder + Postorder

  • Last element of postorder = root.
  • Same split logic using inorder.

You cannot uniquely reconstruct a binary tree from just one traversal. You always need inorder + one of (preorder or postorder). Exception: if the tree is a BST, inorder alone suffices since it gives sorted values.


8. Extra Pointers Worth Knowing

Null/None paths

When recursing, if not root: return base_case is the standard base case. Be careful about what you return β€” 0, -1, True, False, or None all mean different things depending on the problem.

Stack-based iterative traversals

Recursive traversals use the call stack implicitly. For very deep trees (risk of stack overflow), iterative versions using an explicit stack are safer.

# Iterative inorder
def inorder_iter(root):
    stack, result = [], []
    curr = root
    while curr or stack:
        while curr:
            stack.append(curr)
            curr = curr.left
        curr = stack.pop()
        result.append(curr.val)
        curr = curr.right
    return result

Morris Traversal

Inorder traversal in O(1) space (no stack, no recursion) using temporary thread links. Rarely asked but impressive to know.

LCA (Lowest Common Ancestor)

The LCA of two nodes p and q is the deepest node that is an ancestor of both.

def lca(root, p, q):
    if not root or root == p or root == q:
        return root
    left  = lca(root.left, p, q)
    right = lca(root.right, p, q)
    if left and right:
        return root   # p and q are on opposite sides
    return left or right

Common Interview Problem Categories

  • Path problems: max path sum, root-to-leaf paths, path sum equals target
  • View problems: left view, right view, top view, bottom view (level order + tracking)
  • Symmetry / Mirror: check if tree is symmetric, invert a binary tree
  • Serialization: encode a tree to string and decode it back
  • BST-specific: validate BST, kth smallest, range sum
  • Construction: build from traversals, construct BST from preorder

Array representation (for complete binary trees)

Same index formula as heaps:

  • Left child of i β†’ 2*i + 1
  • Right child of i β†’ 2*i + 2
  • Parent of i β†’ (i-1) // 2