← All articles
13 min read

Binary Tree Interview Questions: Patterns and Templates (2026)

Almost every binary tree interview question is one of five recursion templates in disguise. Learn the five, then use the 30-problem mapping table to practice recognizing them.

Binary tree interview questions test whether you can define a recursive subproblem and combine results correctly. Nearly every one of them, from Maximum Depth to Serialize and Deserialize Binary Tree, is solved by one of five templates: top-down DFS, bottom-up DFS, BFS level order, BST ordering, or divide-and-construct. If you can name the template within the first two minutes, the rest is filling in the blanks.

This guide gives you the vocabulary, the five templates in Python, and a table mapping 30 common tree problems to the template that solves each.

Key Takeaways

  • Five templates cover almost all binary tree interview questions. Pick the template first, then write code.
  • The core decision is direction: does a node need information from its ancestors (top-down) or from its descendants (bottom-up)?
  • Bottom-up problems often track two values: what the function returns to its parent, and a global best that it updates on the side. Diameter and Maximum Path Sum both work this way.
  • BST problems are about ordering: inorder traversal yields sorted values, and min/max bounds validate structure.
  • Most tree solutions are O(n) time and O(h) space. Say "h is log n if balanced, n if skewed" to show you know the difference.

What Tree Terms and Traversals Do You Need to Know?

A binary tree is a hierarchical structure in which every node has at most two children, called left and right. Interviewers assume you know the vocabulary and will not stop to define it, so get it straight before your first round.

TermMeaning
RootThe top node, with no parent
LeafA node with no children
Depth of a nodeNumber of edges from the root down to it
Height of a treeNumber of edges (or nodes, by some conventions) on the longest root-to-leaf path
BalancedFor every node, left and right subtree heights differ by at most 1
CompleteEvery level full except possibly the last, which fills left to right
FullEvery node has 0 or 2 children
Binary search tree (BST)For every node, all left-subtree values are smaller and all right-subtree values are larger

Conventions vary: LeetCode's Maximum Depth counts nodes, so a single node has depth 1. State yours out loud.

A tree traversal is an order for visiting every node exactly once. There are four you must know:

  • Preorder (node, left, right): process a node before its children. Used for copying and serializing trees.
  • Inorder (left, node, right): on a BST, this visits values in sorted order.
  • Postorder (left, right, node): process children before the parent. This is the shape of every bottom-up solution.
  • Level order: visit nodes level by level using a queue. This is BFS.

The first three are all depth-first search. The only difference is where the "process node" line sits relative to the two recursive calls:

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

def traverse(node, out):
    if not node:
        return
    # preorder: out.append(node.val) here
    traverse(node.left, out)
    # inorder: out.append(node.val) here
    traverse(node.right, out)
    # postorder: out.append(node.val) here

For iterative traversal, use the inorder loop in the BST section below. For a broader refresher on recursion itself, see our recursion and backtracking interview guide.

Template 1: Top-Down DFS (Pass State Down)

Top-down DFS is a recursion where each call receives information from its ancestors through parameters and uses it at the current node. Think of it as preorder with extra arguments.

Use it when the answer at a node depends on the path from the root: a running sum, the maximum value seen so far, the current depth, or an allowed value range.

def count_good_nodes(root):
    def dfs(node, max_so_far):
        if not node:
            return 0
        good = 1 if node.val >= max_so_far else 0
        new_max = max(max_so_far, node.val)
        return good + dfs(node.left, new_max) + dfs(node.right, new_max)
    return dfs(root, float("-inf"))

This is Count Good Nodes in Binary Tree (1448). A node is "good" if no ancestor has a larger value, so each call needs to know the largest value on the path above it. That fact can only flow downward.

The same skeleton solves Path Sum (112): pass remaining = target - node.val down, and check remaining == 0 at a leaf. For Path Sum II (113), also pass a path list: append before recursing, pop afterward. That is backtracking.

Common bug: checking the target at a null node instead of at a leaf. A node with one child is not a leaf, and testing at null will count paths that stop halfway down.

Template 2: Bottom-Up DFS (The Recursive Return-Value Pattern)

Bottom-up DFS is a recursion where each call returns a summary of its subtree, and the parent computes its own answer from its children's return values. It is postorder traversal with a return value, and it is the single most important pattern for binary tree interview questions.

Before writing any code, answer one question: "What should this function return about the subtree rooted at node?" Height, sum, is-balanced, or "the target node if found here." Once that is precise, the code nearly writes itself.

def max_depth(root):
    if not root:
        return 0
    return 1 + max(max_depth(root.left), max_depth(root.right))

The return-versus-record split

Harder bottom-up problems separate two things: the value you return to the parent and the answer you record globally. Diameter of Binary Tree (543) is the classic example. The longest path may bend through a node, using both children, but a parent can only extend a path that comes up through one child.

def diameter_of_binary_tree(root):
    best = 0
    def height(node):
        nonlocal best
        if not node:
            return 0
        left = height(node.left)
        right = height(node.right)
        best = max(best, left + right)
        return 1 + max(left, right)
    height(root)
    return best

The function returns a one-sided height but records a two-sided path. Binary Tree Maximum Path Sum (124), a LeetCode Hard, is the same code with two tweaks: use node values instead of edge counts, and clamp negative child contributions to zero with max(0, left). If you understand why Diameter works, Max Path Sum stops being hard.

Lowest common ancestor

The lowest common ancestor (LCA) of two nodes is the deepest node that has both as descendants, where a node counts as its own descendant. LCA of a Binary Tree (236) uses the return value as a signal: "a target node I found below me, or null."

def lowest_common_ancestor(root, p, q):
    if not root or root is p or root is q:
        return root
    left = lowest_common_ancestor(root.left, p, q)
    right = lowest_common_ancestor(root.right, p, q)
    if left and right:
        return root
    return left or right

If both subtrees report a hit, the current node is where the two paths split, so it is the answer. This relies on the problem's guarantee that both nodes exist in the tree. If an interviewer removes that guarantee, you need to count matches rather than return early, which is a common follow-up.

When top-down fails, try bottom-up. Balanced Binary Tree (110) solved top-down calls height from every node, which is O(n²) on a skewed tree. Solved bottom-up, returning height or -1 for "unbalanced," it is O(n).

Bottom-up recursion is where most candidates freeze: you know the function should return something, but not what. TechScreen is an invisible AI interview assistant that suggests the right return value and template in real time during a live coding round. Start with 3 free tokens.

Get started free →

Template 3: BFS Level Order

BFS level order is an iterative traversal that processes the tree one level at a time using a queue. The key trick is to snapshot the queue length at the start of each level, so you know exactly which nodes belong to it.

from collections import deque

def level_order(root):
    if not root:
        return []
    result = []
    queue = deque([root])
    while queue:
        level = []
        for _ in range(len(queue)):
            node = queue.popleft()
            level.append(node.val)
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)
        result.append(level)
    return result

Use it when the problem mentions levels, rows, depth-by-depth output, "closest to the root," or "minimum depth." Most variations change only what you do with each level list:

  • Binary Tree Right Side View (199): keep the last value of each level.
  • Zigzag Level Order (103): reverse every other level.
  • Minimum Depth (111): return the depth of the first leaf you dequeue. BFS beats DFS here because it can stop early.
  • Maximum Width (662): store (node, index) pairs where children get 2*i and 2*i + 1, and take last index minus first index plus one per level.

This queue-based structure is the same BFS you use on graphs, covered in our graph algorithms coding interview guide.

Template 4: BST Techniques (Ordering and Bounds)

A binary search tree interview question almost always wants you to use the ordering property. If you solve a BST problem with generic tree code that ignores ordering, expect the interviewer to ask, "Can you use the fact that it is a BST?"

Three techniques cover nearly all of them.

1. Inorder gives sorted order. Kth Smallest Element in a BST (230) is an inorder traversal that stops at the kth node. The iterative form lets you stop early cleanly:

def kth_smallest(root, k):
    stack = []
    node = root
    while stack or node:
        while node:
            stack.append(node)
            node = node.left
        node = stack.pop()
        k -= 1
        if k == 0:
            return node.val
        node = node.right

The same loop powers BST Iterator (173) and Minimum Absolute Difference in BST (530).

2. Bounds validate structure. Validate Binary Search Tree (98) is a top-down problem. Comparing a node only to its direct children is the classic wrong answer, because a value deep in the left subtree must still be less than the root. Pass an allowed (low, high) range down instead:

def is_valid_bst(root):
    def valid(node, low, high):
        if not node:
            return True
        if not (low < node.val < high):
            return False
        return valid(node.left, low, node.val) and valid(node.right, node.val, high)
    return valid(root, float("-inf"), float("inf"))

3. Walk one path, not the whole tree. Search, insert, and LCA of a BST (235) only need one root-to-node path, so they run in O(h). For LCA, if both values are smaller than the current node go left, if both are larger go right, and otherwise you are at the split point.

Template 5: Serialization and Construction (Divide and Construct)

Construction problems build a tree from a description, and serialization problems turn a tree into a string and back. Both use divide and conquer: identify the root, split the remaining input into left and right parts, and recurse.

Construct from Preorder and Inorder (105). Preorder's first element is the root. Find it in the inorder array: everything to its left forms the left subtree, everything to its right forms the right subtree. Use a hash map from value to inorder index so each lookup is O(1), giving O(n) total instead of O(n²).

def build_tree(preorder, inorder):
    index = {val: i for i, val in enumerate(inorder)}
    pre_iter = iter(preorder)
    def build(lo, hi):
        if lo > hi:
            return None
        val = next(pre_iter)
        node = TreeNode(val)
        mid = index[val]
        node.left = build(lo, mid - 1)
        node.right = build(mid + 1, hi)
        return node
    return build(0, len(inorder) - 1)

Building the left subtree before the right matters, because that is the order in which preorder hands out values. The postorder-and-inorder version (106) consumes postorder from the end and builds right before left. This approach assumes unique values, which is worth confirming with your interviewer.

Serialize and Deserialize Binary Tree (297). Write a preorder traversal that emits a marker such as # for null children. The null markers make the encoding unambiguous, so a single traversal is enough to rebuild the tree.

def serialize(root):
    out = []
    def dfs(node):
        if not node:
            out.append("#")
            return
        out.append(str(node.val))
        dfs(node.left)
        dfs(node.right)
    dfs(root)
    return ",".join(out)

def deserialize(data):
    vals = iter(data.split(","))
    def build():
        val = next(vals)
        if val == "#":
            return None
        node = TreeNode(int(val))
        node.left = build()
        node.right = build()
        return node
    return build()

For a BST (449), you can drop the null markers, since preorder plus the bounds technique from Template 4 is enough to rebuild the tree.

Practice Mapping Table: 30 Tree Questions to 5 Templates

Use this table in two passes. First, solve problems by template to build fluency. Then shuffle the list and name the template before writing code. Problem numbers refer to LeetCode.

#ProblemDifficultyTemplateKey idea
104Maximum Depth of Binary TreeEasy2 Bottom-up1 + max of children
226Invert Binary TreeEasy2 Bottom-upSwap children, return node
100Same TreeEasy2 Bottom-upCompare values, recurse in pairs
101Symmetric TreeEasy2 Bottom-upCompare left.left with right.right
572Subtree of Another TreeEasy2 Bottom-upSame Tree at every node
543Diameter of Binary TreeEasy2 Bottom-upReturn height, record left + right
110Balanced Binary TreeEasy2 Bottom-upReturn -1 as failure signal
236LCA of a Binary TreeMedium2 Bottom-upReturn found node or null
124Binary Tree Maximum Path SumHard2 Bottom-upClamp negatives, record bend
114Flatten Binary Tree to Linked ListMedium2 Bottom-upReturn tail of flattened subtree
337House Robber IIIMedium2 Bottom-upReturn (rob, skip) pair
979Distribute Coins in Binary TreeMedium2 Bottom-upReturn excess coins, sum moves
968Binary Tree CamerasHard2 Bottom-upReturn one of three states
112Path SumEasy1 Top-downPass remaining sum, check at leaf
113Path Sum IIMedium1 Top-downPass path, append and pop
129Sum Root to Leaf NumbersMedium1 Top-downPass number * 10 + val
1448Count Good NodesMedium1 Top-downPass max on path
437Path Sum IIIMedium1 Top-downPrefix sums in a hash map
102Level Order TraversalMedium3 BFSSnapshot queue length
103Zigzag Level OrderMedium3 BFSReverse alternate levels
199Right Side ViewMedium3 BFSLast node per level
111Minimum DepthEasy3 BFSFirst leaf wins
662Maximum WidthMedium3 BFSIndex children 2i, 2i + 1
98Validate BSTMedium4 BSTPass (low, high) bounds
230Kth Smallest in a BSTMedium4 BSTIterative inorder, stop at k
235LCA of a BSTMedium4 BSTWalk to the split point
450Delete Node in a BSTMedium4 BSTSwap with inorder successor
108Sorted Array to BSTEasy5 ConstructMiddle element is root
105Construct from Preorder and InorderMedium5 ConstructRoot from preorder, split by inorder index
297Serialize and Deserialize Binary TreeHard5 ConstructPreorder with null markers

A few entries mix templates. Path Sum III combines top-down DFS with the prefix-sum hash map from our coding interview patterns cheat sheet. House Robber III is tree DP: returning a pair of values per node is the bottom-up template applied to an optimization problem, which our dynamic programming patterns guide covers under tree DP.

Many of these appear on the standard curated lists; our comparison of Blind 75, NeetCode 150, and Grind 75 helps you pick one.

How Should You Approach a Tree Question in the Interview?

Name the template before you write a line of code. A short routine keeps you from coding in the wrong direction:

  1. Clarify the node shape and edge cases. Can the tree be empty? Are values unique? Can they be negative? Negative values change Max Path Sum and break many "early exit" tricks.
  2. Ask the direction question. Does a node need its ancestors' context (top-down), its children's results (bottom-up), or its level (BFS)? Is the tree a BST?
  3. Define the function's contract in one sentence. "Returns the height of this subtree, or -1 if it is unbalanced." Say it out loud. Our guide on how to think out loud in a coding interview explains why this narration matters as much as the code.
  4. Write the base case first. Usually if not node: return <identity value>.
  5. Trace a three-node example. Walk through a root with two leaves before you claim the code works.
  6. State complexity. O(n) time, O(h) space for DFS, O(w) for BFS. If you need a refresher on the notation, use our Big O notation cheat sheet.

If step 2 stalls, try both directions on the three-node example. For more recovery tactics, see what to do when you are stuck in a coding interview.

Five templates are easy to learn at your desk and harder to recall when a live interviewer is watching. TechScreen listens to the question and suggests the matching tree template, edge cases, and complexity in real time, invisibly during your screen share. Try it on a mock round with 3 free tokens.

Get started free →

Frequently Asked Questions

What are the most common binary tree interview questions?

The questions that come up most often are Maximum Depth of Binary Tree, Invert Binary Tree, Same Tree, Diameter of Binary Tree, Binary Tree Level Order Traversal, Validate Binary Search Tree, Lowest Common Ancestor, Kth Smallest Element in a BST, Binary Tree Maximum Path Sum, Construct Binary Tree from Preorder and Inorder Traversal, and Serialize and Deserialize Binary Tree. Most of them appear on popular lists like Blind 75 and NeetCode 150, so they are a reliable core to master first.

What is the difference between top-down and bottom-up recursion on a tree?

Top-down recursion passes information from parent to child through function arguments, such as the current path sum or the allowed value range, and usually records answers when it reaches a node or leaf. Bottom-up recursion has each call return a value about its subtree, such as height or subtree sum, and the parent combines its children's results. Use top-down when a node needs context from its ancestors, and bottom-up when a node needs facts about its descendants.

Should I use recursion or iteration for tree problems in an interview?

Recursion is the default because it is shorter and maps directly onto the tree's structure, and interviewers expect it. Switch to iteration when the tree can be very deep, since a skewed tree with 100,000 nodes can exceed Python's default recursion limit of about 1,000 frames, or when the problem is naturally level based, where BFS with a queue is clearer. Mentioning this trade-off unprompted is a good signal.

How do you find the lowest common ancestor in a binary tree?

In a general binary tree, recurse bottom-up: if the current node is null or equals either target, return it. Otherwise recurse left and right. If both sides return a non-null node, the current node is the lowest common ancestor; if only one side does, return that side's result. This runs in O(n) time. In a binary search tree you can do better by walking down from the root and going left or right based on how both target values compare to the current node.

What is the time complexity of most binary tree problems?

Most binary tree solutions visit each node once, so they run in O(n) time. Space is O(h) for the recursion stack, where h is the tree's height: O(log n) for a balanced tree and O(n) for a skewed one. BFS uses O(w) space, where w is the maximum width of any level, which can reach about n/2 in a complete tree. BST search and insertion are O(h), which is only O(log n) if the tree is balanced.

How many tree problems should I practice before a coding interview?

Around 20 to 30 well-chosen tree problems is enough for most candidates, provided they cover all five templates: top-down DFS, bottom-up DFS, BFS level order, BST techniques, and construction or serialization. Spread practice so you solve four to six problems per template, then finish with a mixed set where you must identify the template yourself. Recognition is the skill being tested, not raw volume.

Why do interviewers like binary tree questions?

Tree questions test recursion, which reveals whether a candidate can define a subproblem, trust the recursive call, and handle base cases cleanly. They are short to state, have clean O(n) solutions, and scale easily in difficulty, from Maximum Depth as a warm-up to Binary Tree Maximum Path Sum as a hard follow-up. That makes them efficient for a 45-minute round.

Ready to use AI assistance in your next interview?

TechScreen is the invisible AI assistant trusted by engineers interviewing at Google, Meta, Amazon, and hundreds of other companies. Start with 3 free tokens — no credit card required.

Ace your next interview →