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.
| Term | Meaning |
|---|---|
| Root | The top node, with no parent |
| Leaf | A node with no children |
| Depth of a node | Number of edges from the root down to it |
| Height of a tree | Number of edges (or nodes, by some conventions) on the longest root-to-leaf path |
| Balanced | For every node, left and right subtree heights differ by at most 1 |
| Complete | Every level full except possibly the last, which fills left to right |
| Full | Every 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.
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 get2*iand2*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.
| # | Problem | Difficulty | Template | Key idea |
|---|---|---|---|---|
| 104 | Maximum Depth of Binary Tree | Easy | 2 Bottom-up | 1 + max of children |
| 226 | Invert Binary Tree | Easy | 2 Bottom-up | Swap children, return node |
| 100 | Same Tree | Easy | 2 Bottom-up | Compare values, recurse in pairs |
| 101 | Symmetric Tree | Easy | 2 Bottom-up | Compare left.left with right.right |
| 572 | Subtree of Another Tree | Easy | 2 Bottom-up | Same Tree at every node |
| 543 | Diameter of Binary Tree | Easy | 2 Bottom-up | Return height, record left + right |
| 110 | Balanced Binary Tree | Easy | 2 Bottom-up | Return -1 as failure signal |
| 236 | LCA of a Binary Tree | Medium | 2 Bottom-up | Return found node or null |
| 124 | Binary Tree Maximum Path Sum | Hard | 2 Bottom-up | Clamp negatives, record bend |
| 114 | Flatten Binary Tree to Linked List | Medium | 2 Bottom-up | Return tail of flattened subtree |
| 337 | House Robber III | Medium | 2 Bottom-up | Return (rob, skip) pair |
| 979 | Distribute Coins in Binary Tree | Medium | 2 Bottom-up | Return excess coins, sum moves |
| 968 | Binary Tree Cameras | Hard | 2 Bottom-up | Return one of three states |
| 112 | Path Sum | Easy | 1 Top-down | Pass remaining sum, check at leaf |
| 113 | Path Sum II | Medium | 1 Top-down | Pass path, append and pop |
| 129 | Sum Root to Leaf Numbers | Medium | 1 Top-down | Pass number * 10 + val |
| 1448 | Count Good Nodes | Medium | 1 Top-down | Pass max on path |
| 437 | Path Sum III | Medium | 1 Top-down | Prefix sums in a hash map |
| 102 | Level Order Traversal | Medium | 3 BFS | Snapshot queue length |
| 103 | Zigzag Level Order | Medium | 3 BFS | Reverse alternate levels |
| 199 | Right Side View | Medium | 3 BFS | Last node per level |
| 111 | Minimum Depth | Easy | 3 BFS | First leaf wins |
| 662 | Maximum Width | Medium | 3 BFS | Index children 2i, 2i + 1 |
| 98 | Validate BST | Medium | 4 BST | Pass (low, high) bounds |
| 230 | Kth Smallest in a BST | Medium | 4 BST | Iterative inorder, stop at k |
| 235 | LCA of a BST | Medium | 4 BST | Walk to the split point |
| 450 | Delete Node in a BST | Medium | 4 BST | Swap with inorder successor |
| 108 | Sorted Array to BST | Easy | 5 Construct | Middle element is root |
| 105 | Construct from Preorder and Inorder | Medium | 5 Construct | Root from preorder, split by inorder index |
| 297 | Serialize and Deserialize Binary Tree | Hard | 5 Construct | Preorder 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:
- 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.
- 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?
- 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.
- Write the base case first. Usually
if not node: return <identity value>. - Trace a three-node example. Walk through a root with two leaves before you claim the code works.
- 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.
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 →