Senior 4 min · March 06, 2026

Tree Interview Problems — Stack Overflow on 50k-Node Trees

StackOverflowError from recursive maxDepth on 50k-node degenerate tree? Avoid recursive DFS — proven production fix that beats memorization.

N
Naren · Founder
Plain-English first. Then code. Then the interview question.
About
 ● Production Incident 🔎 Debug Guide
Quick Answer
  • Tree interview problems follow 5 core patterns: DFS, BFS, two-pointer, post-order gather, and pre-order serialization
  • Recursive DFS is clean but risks stack overflow on deep trees, use iterative stack for production code
  • BFS uses Queue and is best for level-order, shortest path, and right-side view
  • Two-pointer technique (e.g., isSameTree) checks structural identity, not just value equality
  • Biggest mistake: assuming a Binary Tree is a BST — never use sortedness without verifying the property
Plain-English First

Imagine a company org chart: the CEO is at the top, managers branch out below them, and individual contributors sit at the leaves. A tree data structure works exactly like that — one root, branches splitting off, ending in leaves with no children. Nearly every hard interview problem that looks complicated is actually just asking you to navigate or compare parts of that org chart in a clever way. Once you see the shape of the problem, the solution almost writes itself.

Trees show up in interviews more than almost any other data structure — and for good reason. File systems, DOM trees, database indexes (B-trees), routing tables, and compiler parse trees are all trees in disguise. A candidate who can fluently navigate a tree signals that they understand recursion, stack/queue trade-offs, and hierarchical thinking. That is a rare combination, and interviewers know it.

The frustrating part is that most candidates memorize solutions instead of patterns. They grind LeetCode until they've seen 'invert binary tree' a hundred times, but the moment an interviewer tweaks the problem slightly — 'now do it iteratively' or 'what if nodes have parent pointers?' — they freeze. The real skill isn't knowing answers, it's recognizing which of the five or six fundamental tree patterns applies to a new problem you've never seen before.

By the end of this article you'll have a mental toolkit of those patterns: DFS vs BFS trade-offs, the two-pointer trick adapted for trees, the post-order 'gather-then-decide' approach, and more. Every problem below is chosen because it directly teaches a transferable pattern. Work through the code, tweak the inputs, break it — that's how the pattern becomes muscle memory.

Pattern 1: Depth-First Search (DFS) & Recursive Bottom-Up

Depth-First Search is the bread and butter of tree manipulation. In a recursive bottom-up approach, you process children first and then return information to the parent. This is essential for problems like calculating the 'Maximum Depth' or 'Diameter of a Binary Tree.' By thinking of each node as the 'root' of its own sub-tree, you build a solution for the entire tree through sub-problem results.

Recursive DFS is elegant but risks stack overflow on deep trees — the JVM default stack size is about 1 MB, and each recursion frame costs ~48 bytes (plus object overhead). A degenerate tree with 20,000 nodes will overflow. Always ask the interviewer about the tree size before committing to recursion.

io/thecodeforge/trees/DepthCalculator.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package io.thecodeforge.trees;

/**
 * io.thecodeforge: Efficiently calculating the maximum depth of a Binary Tree.
 * Pattern: Recursive DFS (Post-order)
 */
public class DepthCalculator {
    public int maxDepth(TreeNode root) {
        // Base Case: An empty tree has depth 0
        if (root == null) {
            return 0;
        }

        // Recursive Step: Gather information from children
        int leftDepth = maxDepth(root.left);
        int rightDepth = maxDepth(root.right);

        // Combine Step: Current depth is max of children + 1 (itself)
        return Math.max(leftDepth, rightDepth) + 1;
    }
}

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}
Output
// Input: [3,9,20,null,null,15,7] -> Output: 3
Forge Tip:
Type this code yourself rather than copy-pasting. The muscle memory of writing it will help it stick. Remember: Recursion always needs a solid base case (usually root == null) or you'll hit a StackOverflowError.
Production Insight
Recursive DFS on a degenerate tree of 50k nodes crashed a production batch job.
Fix: Replace recursion with an explicit Stack<TreeNode> and iterative DFS.
Rule: When tree depth is unbounded, use iterative traversal — always.
Key Takeaway
Recursive DFS is built on post-order logic: children first, then parent.
Iterative DFS uses an explicit stack — safer for deep or unbalanced trees.
Choose based on tree shape, not habit.
When to use Recursive DFS vs Iterative DFS
IfTree is balanced (depth ~ log N)
UseRecursive DFS is safe and cleaner.
IfTree could be degenerate (depth ~ N)
UseUse iterative DFS with explicit Stack<TreeNode>.
IfYou need to gather results from children before parent (bottom-up)
UseUse post-order DFS (either recursive or iterative with two passes).

Pattern 2: Breadth-First Search (BFS) & Level-Order Traversal

When an interviewer asks for 'Level Order Traversal' or 'Finding the Right Side View,' you need Breadth-First Search. Unlike DFS, BFS uses a Queue to explore the tree layer-by-layer. This is functionally different from recursion because it explores horizontal relationships before vertical ones.

BFS is also the go-to for shortest path problems in trees (e.g., min depth to a leaf). The space complexity is O(W) where W is maximum width of the tree — in a perfect binary tree, W can be N/2, which is much larger than DFS's O(height). For a chain tree, BFS uses O(1) memory while DFS uses O(N). So there's no universal winner.

io/thecodeforge/trees/LevelExplorer.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package io.thecodeforge.trees;

import java.util.*;

public class LevelExplorer {
    /**
     * io.thecodeforge: Standard Level-Order Traversal implementation.
     */
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> result = new ArrayList<>();
        if (root == null) return result;

        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);

        while (!queue.isEmpty()) {
            int levelSize = queue.size();
            List<Integer> currentLevel = new ArrayList<>();

            for (int i = 0; i < levelSize; i++) {
                TreeNode node = queue.poll();
                currentLevel.add(node.val);

                if (node.left != null) queue.offer(node.left);
                if (node.right != null) queue.offer(node.right);
            }
            result.add(currentLevel);
        }
        return result;
    }
}
Output
// Returns nodes grouped by their vertical level.
Interview Logic:
Mention the Space Complexity! BFS takes $O(W)$ space, where $W$ is the maximum width of the tree. In a perfect binary tree, the width can be $N/2$, which makes BFS more memory-intensive than DFS for deep, narrow trees.
Production Insight
BFS is excellent for level-order view but watch memory: a perfect tree of 10^6 nodes will have ~500k nodes in the queue at the last level.
Use DFS iterative for narrow trees; BFS for wide trees.
Trade-off: BFS guarantees shortest path in unweighted trees, DFS does not.
Key Takeaway
BFS is level-order: queue in, process out.
Space depends on max width, not depth.
For shortest paths in unweighted trees, BFS wins.
BFS vs DFS Decision
IfNeed shortest path to a leaf (minimum depth)
UseUse BFS — it finds the first leaf fastest.
IfNeed to process all nodes in level order
UseUse BFS (queue).
IfTree is deep and narrow (e.g., chain)
UseDFS uses O(height) space, BFS uses O(1) — but BFS queue is tiny anyway. Either works.

Pattern 3: Two-Pointer Technique for Trees (Structural Comparison)

The two-pointer technique, common in arrays and linked lists, adapts beautifully to trees. Problems like 'Same Tree', 'Symmetric Tree', and 'Subtree of Another Tree' ask you to compare two trees simultaneously. The pattern: traverse both trees in lockstep, comparing each node and its children.

For 'Same Tree', you recursively (or iteratively) check if both current nodes are null (equal), both non-null with same value, and then recursively check left and right children. The base case must handle nulls correctly—most mistakes come from failing to consider that one tree might have a null where the other doesn't.

For 'Symmetric Tree', you compare the left subtree with the flipped right subtree. A common trick: convert the problem into a 'Same Tree' comparison where you compare the original tree's left with its own right (mirrored).

io/thecodeforge/trees/TreeComparison.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package io.thecodeforge.trees;

public class TreeComparison {
    // Pattern: Two-pointer recursion — compare two nodes simultaneously
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if (p == null && q == null) return true;
        if (p == null || q == null) return false;
        if (p.val != q.val) return false;
        return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
    }

    public boolean isSymmetric(TreeNode root) {
        if (root == null) return true;
        return isMirror(root.left, root.right);
    }

    private boolean isMirror(TreeNode left, TreeNode right) {
        if (left == null && right == null) return true;
        if (left == null || right == null) return false;
        return (left.val == right.val)
            && isMirror(left.left, right.right)
            && isMirror(left.right, right.left);
    }
}
Output
// isSameTree([1,2,3], [1,2,3]) -> true
// isSymmetric([1,2,2,3,4,4,3]) -> true
Common Pitfall: Null Check Order
Always check both null first, then one null. If you check if (p == null || q == null) before the both-null check, you'll return false prematurely when both are null.
Production Insight
A production mis-ordered null check caused a structural comparison bug: the code returned false for identical trees when both children were null.
Fix: swap the order of checks — both-null first.
Rule: In two-pointer tree comparisons, always handle the base case of both null before checking for mismatch.
Key Takeaway
Two-pointer on trees means simultaneous traversal.
Base case order matters: both null before mismatch.
Symmetric tree = compare left with mirrored right.
When to Use Two-Pointer Tree Traversal
IfComparing two trees for equality
UseUse recursive two-pointer (lockstep).
IfChecking if a tree is symmetric
UseUse isMirror with two pointers: left vs right reversed.
IfChecking if one tree is subtree of another
UseUse two-pointer recursively with outer traversal (e.g., DFS on main tree, then isSameTree for each node).

Pattern 4: Post-Order Gather-Then-Decide (Bottom-Up Aggregation)

Some problems require each node to collect information from its children, then decide a property for itself. Classic examples: 'Diameter of Binary Tree', 'Maximum Path Sum', 'Balanced Binary Tree Check'. The pattern: compute a value for the subtree (e.g., height), then combine children's results to determine something about the current node (e.g., diameter = max(diameter, leftHeight + rightHeight)).

This is distinct from simple depth calculation because you're not just returning a single value to the parent—you're also maintaining a global or passed-by-reference variable for the overall answer. In 'Diameter of a Binary Tree', the function returns height but updates a max diameter. In 'Maximum Path Sum', the function returns the maximum path sum starting from that node downwards, while a global variable tracks the max path that goes through the node.

io/thecodeforge/trees/BottomUpAggregator.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package io.thecodeforge.trees;

public class BottomUpAggregator {
    private int diameter = 0;

    public int diameterOfBinaryTree(TreeNode root) {
        height(root);
        return diameter;
    }

    private int height(TreeNode node) {
        if (node == null) return 0;
        int leftHeight = height(node.left);
        int rightHeight = height(node.right);
        // Update diameter: longest path through this node
        diameter = Math.max(diameter, leftHeight + rightHeight);
        // Return height of this node to parent
        return Math.max(leftHeight, rightHeight) + 1;
    }

    // Maximum Path Sum variant (LeetCode 124)
    private int maxPathSum = Integer.MIN_VALUE;

    public int maxPathSum(TreeNode root) {
        maxGain(root);
        return maxPathSum;
    }

    private int maxGain(TreeNode node) {
        if (node == null) return 0;
        int leftGain = Math.max(0, maxGain(node.left));  // ignore negative gains
        int rightGain = Math.max(0, maxGain(node.right));
        int currentMax = node.val + leftGain + rightGain;
        maxPathSum = Math.max(maxPathSum, currentMax);
        // Return the maximum sum if you go down one path from this node
        return node.val + Math.max(leftGain, rightGain);
    }
}
Output
// Input: [1,2,3,4,5] -> diameter = 3 (path 4->2->1->3)
// Input: [-10,9,20,null,null,15,7] -> maxPathSum = 42 (15->20->7)
Mental Model: The Two-Level Return
  • The return value is what the parent needs (height, maxGain).
  • The global variable holds the problem's answer (diameter, maxPathSum).
  • The combination step (left+right) updates the global answer.
  • The return step selects the best single path to continue upward.
Production Insight
A common bug in production code: using the returned value instead of the global variable — the function returns the branch sum but you print the returned value thinking it's the answer.
Fix: always read the class-level variable after traversal.
Rule: In bottom-up aggregation, separate the 'return to parent' from the 'global answer'.
Key Takeaway
Post-order gather: children return info, parent combines and updates a global or passes up.
Return value helps the parent, global variable holds the answer.
Always ignore negative contributions in path sum: use max(0, ...).

Pattern 5: Pre-Order Serialization & Construction (Tree Building)

Certain tree problems ask you to serialize a tree into a string (or array) and deserialize it back. Examples: 'Serialize and Deserialize Binary Tree', 'Construct Binary Tree from Preorder and Inorder Traversal'. The pattern uses pre-order traversal to create a representation, and then rebuilds the tree from that representation using a queue or index.

For serialization, you traverse pre-order, represent null children with a sentinel (e.g., 'null'), and separate values by a delimiter. The key insight: the serialized string uniquely encodes the tree structure, and the same traversal order (usually pre-order) is used to reconstruct it.

For construction from two traversals (e.g., preorder + inorder), you need both to uniquely identify the tree. Preorder gives you the root (first element), and inorder tells you which values are in left vs right subtree. A recursive approach picks the root from preorder, finds its index in inorder, then recurses on left and right slices.

io/thecodeforge/trees/TreeSerializer.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package io.thecodeforge.trees;

import java.util.*;

public class TreeSerializer {
    private static final String NULL_MARKER = "null";
    private static final String DELIMITER = ",";

    // Serialize using pre-order traversal
    public String serialize(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        serializeHelper(root, sb);
        return sb.toString();
    }

    private void serializeHelper(TreeNode node, StringBuilder sb) {
        if (node == null) {
            sb.append(NULL_MARKER).append(DELIMITER);
            return;
        }
        sb.append(node.val).append(DELIMITER);
        serializeHelper(node.left, sb);
        serializeHelper(node.right, sb);
    }

    // Deserialize using a queue from the serialized array
    public TreeNode deserialize(String data) {
        String[] parts = data.split(DELIMITER);
        Queue<String> queue = new LinkedList<>(Arrays.asList(parts));
        return deserializeHelper(queue);
    }

    private TreeNode deserializeHelper(Queue<String> queue) {
        String val = queue.poll();
        if (val == null || val.equals(NULL_MARKER)) return null;
        TreeNode node = new TreeNode(Integer.parseInt(val));
        node.left = deserializeHelper(queue);
        node.right = deserializeHelper(queue);
        return node;
    }
}
Output
// serialize([1,2,3,null,null,4,5]) -> "1,2,null,null,3,4,null,null,5,null,null,"
// deserialize(above) -> same tree
Null Handling Gotcha
If you forget to append a null marker for absent children, the deserialization will misalign indices and reconstruct a wrong tree. Always encode both left and right nulls explicitly.
Production Insight
A team serialized tree nodes without null markers for children, relying on knowing tree depth. After a schema change, the deserialization broke because nodes had missing children.
Fix: always encode null children as sentinel values.
Rule: Serialization format must be self-contained — never assume external knowledge about tree depth or shape.
Key Takeaway
Pre-order serialization + queue → full tree reconstruction.
Null markers are required for unambiguous representation.
Given two traversals, preorder gives root, inorder splits subtrees.
Serialization Strategy Selection
IfNeed to store/reconstruct tree exactly
UseUse pre-order with null markers — simplest and space-efficient.
IfNeed to represent tree in human-readable format
UseUse level-order (BFS) representation: [1,2,3,null,null,4,5]
IfGiven two traversals (e.g., inorder+preorder) to reconstruct tree
UseUse recursive index-based construction with HashMap for inorder lookup.

Pattern 6: In-Order Traversal for BST Validation & Sorted Output

In-order traversal of a Binary Search Tree yields nodes in ascending order. This property is the foundation of two big problems: 'Validate Binary Search Tree' and 'Kth Smallest Element in a BST'. The pattern: traverse in-order, track the last visited value, and compare.

For BST validation, you need to ensure that the current node's value is greater than the previous node's value (strictly). A recursive approach passes a valid range (min, max) down the tree. The iterative in-order traversal using a stack is also popular because it avoids recursion overhead and can early exit when a violation is found.

For Kth Smallest, you can stop the traversal after processing k nodes. The iterative stack approach shines here: pop k times and return the kth popped value.

io/thecodeforge/trees/BSTValidator.javaJAVA
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package io.thecodeforge.trees;

import java.util.*;

public class BSTValidator {
    // Recursive range-based validation
    public boolean isValidBST(TreeNode root) {
        return validate(root, null, null);
    }

    private boolean validate(TreeNode node, Integer low, Integer high) {
        if (node == null) return true;
        if ((low != null && node.val <= low) || (high != null && node.val >= high)) return false;
        return validate(node.left, low, node.val) && validate(node.right, node.val, high);
    }

    // Iterative in-order validation (uses stack) – early exit
    public boolean isValidBSTIterative(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        TreeNode curr = root;
        Integer prev = null;
        while (curr != null || !stack.isEmpty()) {
            while (curr != null) {
                stack.push(curr);
                curr = curr.left;
            }
            curr = stack.pop();
            if (prev != null && curr.val <= prev) return false;
            prev = curr.val;
            curr = curr.right;
        }
        return true;
    }

    // Kth Smallest Element in BST
    public int kthSmallest(TreeNode root, int k) {
        Stack<TreeNode> stack = new Stack<>();
        TreeNode curr = root;
        int count = 0;
        while (curr != null || !stack.isEmpty()) {
            while (curr != null) {
                stack.push(curr);
                curr = curr.left;
            }
            curr = stack.pop();
            count++;
            if (count == k) return curr.val;
            curr = curr.right;
        }
        return -1;
    }
}
Output
// isValidBST([2,1,3]) -> true; [5,1,4,null,null,3,6] -> false
// kthSmallest([3,1,4,null,2], 1) -> 1
Interview Tip: In-order + BST = Sorted
When you hear 'BST' and 'sorted' in the same sentence, your first instinct should be in-order traversal. For validation, ask yourself: does the in-order output increase?
Production Insight
A production system used a range-based recursion to validate a BST that was being built incrementally. The recursion's min/max values overflowed the stack after 10k insertions because the tree was unbalanced.
Fix: switch to iterative in-order stack traversal, which uses O(height) stack space but managed by heap.
Rule: For BST validation in production, prefer iterative in-order to avoid deep recursion and enable early exit.
Key Takeaway
In-order traversal of BST = sorted order.
Validation: either range-based recursion or iterative in-order.
Kth smallest = in-order until count reaches k.
● Production incidentPOST-MORTEMseverity: high

Recursive Stack Overflow on 50,000-Node Tree

Symptom
The Java process logs show a StackOverflowError with the stack trace pointing to the recursive maxDepth method. The error occurs only on the largest XML files (>30MB).
Assumption
The team assumed recursion is safe for tree traversal because depth is usually bounded by log(N). They forgot that an unbalanced tree (e.g., a linked list from a flat XML hierarchy) has depth N.
Root cause
The tree from the XML parser was degenerate (each node had only one child) due to the data structure: a sequence of <item> elements nested inside each other created a linear chain. Recursive DFS then consumed stack depth proportional to 50,000 frames, exceeding the default JVM stack size (typically 1024 KB).
Fix
Replaced the recursive maxDepth with an iterative DFS using an explicit Stack<TreeNode> and a counter per node. Also configured the JVM stack size (Xss) to 2MB as a safety net for other recursions.
Key lesson
  • Never rely on recursion for tree traversal unless you control the tree shape or you've added a depth guard.
  • Always ask: could the tree be degenerate? If yes, use iterative traversal.
  • For production code, prefer iterative BFS or DFS with explicit stack/queue over recursion.
Production debug guideSymptom → Action guide for common tree algorithm failures5 entries
Symptom · 01
StackOverflowError in recursive traversal
Fix
Switch to iterative DFS with Stack<TreeNode> or BFS with Queue<TreeNode>. Add depth limit check if recursion must stay.
Symptom · 02
NullPointerException when accessing left/right child
Fix
Verify all null checks: always check for null before accessing fields. Use Optional<TreeNode> for null-safe traversal.
Symptom · 03
Incorrect tree property (e.g., BST validation fails)
Fix
Print In-order traversal. For a valid BST, the result should be strictly increasing. If not, trace which node violates the property.
Symptom · 04
Wrong level order output (nodes in wrong order)
Fix
Check the BFS queue: ensure you poll from the front and offer children in correct left-to-right order.
Symptom · 05
Infinite loop in iterative traversal
Fix
Add a visited set or a counter to detect cycles. In pure trees cycles should not exist, but graph-like variants might.
★ Tree Traversal Debug Cheat SheetQuick commands and checks for debugging tree traversal in Java/CLI
Recursive StackOverflowError
Immediate action
Add a depth counter and print depth at entry. If depth > 10000, switch to iterative.
Commands
Add a static AtomicInteger recursionDepth = new AtomicInteger(0);
Check with `jstack <pid>` to see the thread stack depth.
Fix now
Replace recursion with iterative DFS using Stack<TreeNode> and a separate stack for depth.
NullPointerException on child access+
Immediate action
Add a null guard before every node.left or node.right access.
Commands
Run with -ea (enable assertions) and add `assert node != null : "Node is null at depth " + depth;`
Log the current node value and its children before access.
Fix now
Check the initial tree construction: are you building the tree correctly? Print tree in level order to verify structure.
Incorrect traversal order (wrong sequence)+
Immediate action
Print the node value when visited.
Commands
Add a debug print: `System.out.println("Visiting: " + node.val);`
Trace by hand on a small sample tree (3–5 nodes).
Fix now
Double-check the algorithm: pre-order (NLR), in-order (LNR), post-order (LRN), level-order (BFS).
Tree Traversal Algorithms Comparison
AlgorithmMechanismBest Used ForTime ComplexitySpace Complexity
DFS (Pre-order)Node -> Left -> RightSerializing/Cloning treesO(N)O(H) — H = height (stack)
DFS (In-order)Left -> Node -> RightValidating BSTs (Returns sorted values)O(N)O(H)
DFS (Post-order)Left -> Right -> NodeDeleting trees, Diameter, DepthO(N)O(H)
BFS (Level-order)Queue-based LayeringLevel order, Shortest path, Right-side viewO(N)O(W) — W = max tree width
Two-Pointer (Lockstep)Recursive comparisonSame Tree, Symmetric TreeO(N)O(H)
Serialization (Pre-order + nulls)Pre-order traversal with sentinelTree serialization/deserializationO(N)O(N) — output string size

Key takeaways

1
You now understand that tree problems are effectively sub-problem puzzles
solve for the child, then the parent.
2
You've seen how io.thecodeforge uses specific data structures (Queue for BFS, Stack/Recursion for DFS) to navigate hierarchies.
3
You understand that In-order traversal on a BST yields sorted results, a major interview 'unlock'.
4
You've learned that bottom-up aggregation separates the return value from the global answer
a pattern used in diameter, max path sum, and balanced tree checks.
5
You know that serialization must include null markers to be unambiguous, and that pre-order encoding works with a queue for reconstruction.
6
Practice daily
the forge only works when it's hot 🔥

Common mistakes to avoid

5 patterns
×

Not handling the null root case

Symptom
NullPointerException when accessing root.left or root.right in a method that expects a non-null root. The algorithm crashes immediately.
Fix
Always add an early return guard: if (root == null) return default value (0, true, empty list, etc.). Then you never dereference null.
×

Confusing Binary Trees with Binary Search Trees (BST)

Symptom
Using BST-specific properties (e.g., left < root < right) on a regular binary tree. The algorithm produces incorrect results, like validating a non-BST as valid.
Fix
Check the problem statement: does it mention BST? If not, assume a generic Binary Tree. For validation, explicitly check the range using min/max parameters.
×

Infinite recursion or stack overflow due to missing base case

Symptom
StackOverflowError on large or degenerate trees. The recursion never reaches a null node because the tree has a cycle (rare) or the base case is omitted.
Fix
Always include a null check as the first line of a recursive function. For iterative traversal, use a visited set or counter to detect cycles. In pure trees, ensure no circular references.
×

Misordering null checks in structural comparison (same tree)

Symptom
Comparing two trees that are both null returns false, or one null and one non-null returns true incorrectly.
Fix
Order: first check if both null -> true; then check if one null -> false; then compare values. That order guarantees correctness.
×

Assuming BFS always uses less memory than DFS

Symptom
OutOfMemoryError in BFS on a balanced tree with millions of nodes because the queue holds half the nodes at the last level.
Fix
Know your tree shape: for wide trees, BFS memory explodes; for deep trees, DFS recursion stack explodes. Choose algorithm based on shape, not assumption.
INTERVIEW PREP · PRACTICE MODE

Interview Questions on This Topic

Q01SENIOR
Write a function to check if a binary tree is symmetric around its cente...
Q02SENIOR
Find the diameter of a binary tree. The diameter is the length of the lo...
Q03SENIOR
Serialize and deserialize a binary tree. The serialized string should be...
Q04SENIOR
Given two binary trees, check if one tree is a subtree of the other.
Q01 of 04SENIOR

Write a function to check if a binary tree is symmetric around its center.

ANSWER
Use a recursive two-pointer approach: a helper method isMirror(left, right) that checks if left.val == right.val, then recursively checks isMirror(left.left, right.right) && isMirror(left.right, right.left). Base case: if both null return true; if one null return false. ``java public boolean isSymmetric(TreeNode root) { return root == null || isMirror(root.left, root.right); } private boolean isMirror(TreeNode t1, TreeNode t2) { if (t1 == null && t2 == null) return true; if (t1 == null || t2 == null) return false; return (t1.val == t2.val) && isMirror(t1.left, t2.right) && isMirror(t1.right, t2.left); } `` Complexity: O(N) time, O(H) space (recursion stack).
FAQ · 5 QUESTIONS

Frequently Asked Questions

01
What is the difference between a Binary Tree and a Binary Search Tree (BST)?
02
Why is recursion used so often for tree problems?
03
What is a 'Balanced' Binary Tree?
04
When should I use iterative DFS over recursive DFS?
05
How do I handle large trees in BFS without running out of memory?
🔥

That's Coding Patterns. Mark it forged?

4 min read · try the examples if you haven't

Previous
Top 10 String Interview Problems
3 / 17 · Coding Patterns
Next
Top 10 DP Interview Problems