Pattern #37

Binary Trees

Important interview questions, thinking patterns, main recursive pattern (Left + Right combine), Mirror symmetry, Diameter vs Max Path Sum, and Go templates.

Must Solve

20 core questions — solve these first.

  1. 1.Maximum Depth of Binary Tree
    easy
  2. 2.Same Tree
    easy
  3. 3.Invert Binary Tree
    easy
  4. 4.Symmetric Tree
    easy
  5. 5.Balanced Binary Tree
    easy
  6. 6.Diameter of Binary Tree
    easy
  7. 7.Binary Tree Level Order Traversal
    medium
  8. 8.Binary Tree Right Side View
    medium
  9. 9.Path Sum
    easy
  10. 10.Path Sum II
    medium
  11. 11.Lowest Common Ancestor of a Binary Tree
    medium
  12. 12.Binary Tree Maximum Path Sum
    hard
  13. 13.Subtree of Another Tree
    easy
  14. 14.Count Good Nodes in Binary Tree
    medium
  15. 15.Construct Binary Tree from Preorder and Inorder Traversal
    medium
  16. 16.Serialize and Deserialize Binary Tree
    hard
  17. 17.Flatten Binary Tree to Linked List
    medium
  18. 18.Binary Tree Zigzag Level Order Traversal
    medium
  19. 19.All Nodes Distance K in Binary Tree
    medium
  20. 20.Maximum Width of Binary Tree
    medium

Also Important

10 more questions worth practicing.

  1. 21.Minimum Depth of Binary Tree
    easy
  2. 22.Sum of Left Leaves
    easy
  3. 23.Binary Tree Paths
    easy
  4. 24.Cousins in Binary Tree
    easy
  5. 25.Vertical Order Traversal
    medium
  6. 26.Boundary Traversal
    medium
  7. 27.House Robber III
    medium
  8. 28.Binary Tree Cameras
    hard
  9. 29.Find Leaves of Binary Tree
    medium
  10. 30.Delete Leaves With a Given Value
    medium

How to Think

  1. Need visit every node?DFS / BFS
  2. Need information from left and right children?Postorder DFS
  3. Need level by level traversal?BFS + Queue
  4. Need root-to-leaf path?DFS + carry state downward
  5. Need longest path / diameter / max path?Get child answers + update global answer

Go Binary Tree Main Recursive Template

Standard 4-Step Recursive Pattern in Go

type TreeNode struct {
    Val   int
    Left  *TreeNode
    Right *TreeNode
}

// Main Pattern: 1. Nil Base Case -> 2. Solve Left -> 3. Solve Right -> 4. Combine
func solveTree(node *TreeNode) int {
    // 1. Handle nil base case
    if node == nil {
        return 0
    }

    // 2. Solve left child
    leftResult := solveTree(node.Left)

    // 3. Solve right child
    rightResult := solveTree(node.Right)

    // 4. Combine answers for current node
    return 1 + max(leftResult, rightResult)
}

👉 Total Time: O(N) | Space: O(H) recursion stack

Main Recursive Pattern & Symmetry

Every binary tree node has at most 2 children (Left & Right). The core recursive strategy boils down to:

// Symmetric Tree Mirror Check
func isSymmetric(root *TreeNode) bool {
    if root == nil {
        return true
    }
    var isMirror func(left, right *TreeNode) bool
    isMirror = func(left, right *TreeNode) bool {
        if left == nil && right == nil {
            return true
        }
        if left == nil || right == nil || left.Val != right.Val {
            return false
        }
        return isMirror(left.Left, right.Right) && isMirror(left.Right, right.Left)
    }
    return isMirror(root.Left, root.Right)
}

👉 Symmetric trees compare mirror opposite branches across the center vertical line!

Diameter & Maximum Path Sum (Global vs Return Value)

In problems like Diameter or Max Path Sum, there is a fundamental distinction between the global candidate answer and the value returned upward:

// Binary Tree Maximum Path Sum
func maxPathSum(root *TreeNode) int {
    maxSum := -1 << 31 // Global answer accumulator

    var getGain func(node *TreeNode) int
    getGain = func(node *TreeNode) int {
        if node == nil {
            return 0
        }

        // Drop negative child contributions (Kadane rule!)
        leftGain := max(0, getGain(node.Left))
        rightGain := max(0, getGain(node.Right))

        // 1. Candidate Global Answer (Uses BOTH branches!)
        currentPathSum := node.Val + leftGain + rightGain
        if currentPathSum > maxSum {
            maxSum = currentPathSum
        }

        // 2. Value Returned Upward (MUST choose ONE branch!)
        return node.Val + max(leftGain, rightGain)
    }

    getGain(root)
    return maxSum
}
Visual Memory Rule
Solve Left  -> Solve Right -> Combine at Node
Global Candidate  → node.Val + left + right (Uses BOTH sides)
Return Upward     → node.Val + max(left, right) (Uses ONE side)
Negative Gain     → max(0, childGain) (Ignore harmful paths!)
Symmetry Mirror   → left.Left <-> right.Right & left.Right <-> right.Left

💡 Golden Rule: "Solve the left subtree, solve the right subtree, then decide what the current node should do with those two answers."

Common Interview Mistakes

1. Forgetting Nil Base Case

Always handle if node == nil { return ... } to prevent dereferencing nil pointers!

2. Returning Both Branches Upward

A path traveling up to a parent CANNOT split into both children! Return node.Val + max(left, right) upward.

3. Assuming Longest Path Passes Root

The tree diameter or maximum path sum may reside entirely within a deep left or right subtree.

4. Confusing Binary Tree With BST

Standard binary trees have NO order guarantee (left < node < right only holds for BSTs).

Interview Rules

  1. 1. Max 2 children per node? → Binary Tree
  2. 2. Level order traversal? → BFS + Queue FIFO
  3. 3. Height / depth / path sum? → DFS + Recursion
  4. 4. Diameter of tree? → Global max(leftHeight + rightHeight) updated at every node
  5. 5. Symmetry check? → Compare mirror opposite sides (left.Left ↔ right.Right)
  6. 6. Negative child path gain? → Ignore it using max(0, childGain)
  7. 7. LCA of 2 nodes?→ Return node if root == p or q; check if left != nil && right != nil
  8. 8. Overall Complexity → Time: O(N) | DFS Space: O(Height) | BFS Space: O(Width)

Small Rules

  1. Rule 1:Each binary tree node has at most 2 children (Left & Right).
  2. Rule 2: Always handle nil base case first (if node == nil { return ... }).
  3. Rule 3: Global candidate answer uses BOTH children; return value upward uses ONLY ONE branch.
  4. Rule 4: Drop negative child gains with max(0, gain).
  5. Rule 5: Carry path state DOWN, return subtree height/gain UP.

Production Thinking

Expression Trees in CompilersSyntax trees representing arithmetic (2 + 3) * 4 parsed recursively

Decision Trees in Rules / MLYes/No binary decision logic branches evaluated per node

Huffman Coding CompressionBinary compression trees encoding symbols as left (0) / right (1) paths

Hierarchical Condition EvaluationEvaluating boolean rule trees in production engines

Remember This

Binary Tree     → Left + Right
DFS             → Subtrees / paths
BFS             → Levels
Preorder        → Root first
Inorder         → Root middle
Postorder       → Root last
Height          → child answers upward
Path Sum        → state downward
Diameter        → left height + right height
LCA             → both sides find target
Normal          → Time O(N), Space O(Height)

💡 Golden Rule: "Solve the left subtree, solve the right subtree, then decide what the current node should do with those two answers."