Bird
Raised Fist0
Interview Preptree-dfseasyAmazonGoogleBloomberg

Balanced Binary Tree

Choose your preparation mode4 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
📋
Problem

Imagine you are designing a system that needs to keep data balanced for efficient retrieval, like a balanced family tree where no branch is too deep compared to others.

Given a binary tree, determine if it is height-balanced. A height-balanced binary tree is defined as a binary tree in which the left and right subtrees of every node differ in height by no more than 1. Input: The root node of a binary tree. Output: Return true if the tree is height-balanced, otherwise false.

1 ≤ n ≤ 10^5 (number of nodes)Node values can be any integerTree can be skewed or complete
Edge cases: Empty tree → true (an empty tree is balanced)Single node tree → true (only one node, balanced)Completely skewed tree (all nodes only on one side) → false
</>
IDE
def isBalanced(root: Optional[TreeNode]) -> bool:public boolean isBalanced(TreeNode root)bool isBalanced(TreeNode* root)function isBalanced(root)
def isBalanced(root):
    # Write your solution here
    pass
class Solution {
    public boolean isBalanced(TreeNode root) {
        // Write your solution here
        return false;
    }
}
#include <vector>
using namespace std;

bool isBalanced(TreeNode* root) {
    // Write your solution here
    return false;
}
function isBalanced(root) {
    // Write your solution here
}
0/9
Common Bugs to Avoid
Wrong: trueFailing to detect imbalance in skewed or deep subtree cases due to missing or incorrect height difference checks.Add condition to return false immediately if abs(left_height - right_height) > 1 at any node.
Wrong: falseIncorrectly returning false for empty or single-node trees by not handling base cases.Return true immediately if root is null or if node has no children.
Wrong: trueNot using early exit, causing incorrect results when imbalance is detected deep in the tree.Implement early exit by returning a sentinel value (e.g., -1) to indicate imbalance and propagate it up.
Wrong: TLEUsing brute force approach that recomputes height for each node causing O(n^2) complexity.Use a single postorder traversal that returns height and balance status simultaneously to achieve O(n).
Test Cases
t1_01basic
Input{"root":[3,9,20,null,null,15,7]}
Expectedtrue

The left subtree height is 1, right subtree height is 2, difference is 1 which is allowed.

t1_02basic
Input{"root":[1,2,2,3,3,null,null,4,4]}
Expectedfalse

The left subtree is deeper by more than 1 level at node 2, so the tree is unbalanced.

t2_01edge
Input{"root":[]}
Expectedtrue

An empty tree is balanced by definition.

t2_02edge
Input{"root":[1]}
Expectedtrue

Single node tree is balanced as both subtrees are empty.

t2_03edge
Input{"root":[1,2,null,3,null,4,null,5]}
Expectedfalse

Completely skewed tree with nodes only on left side is unbalanced.

t3_01corner
Input{"root":[1,2,2,3,null,null,3,4,null,null,4]}
Expectedfalse

Tree where imbalance occurs deep in subtree; tests early exit correctness.

t3_02corner
Input{"root":[1,2,2,3,null,null,3,4,null,null,4,5]}
Expectedfalse

Tests confusion between 0/1 and unbounded recursion: extra nodes cause imbalance.

t3_03corner
Input{"root":[1,2,2,3,3,null,null,4,4,null,null,null,null,5]}
Expectedfalse

Greedy trap: assuming local balance implies global balance is incorrect.

t4_01performance
Input{"root":[1,2,null,3,null,4,null,5,null,6,null,7,null,8,null,9,null,10]}
⏱ Performance - must finish in 2000ms

n=10 (skewed tree) tests O(n) complexity; brute force O(n^2) will time out for large n.

Practice

(1/5)
1. Consider the following iterative postorder traversal code to compute the diameter of a binary tree. Given the tree: 1 / \ 2 3 / 4 What is the final value of the variable diameter after the function completes?
easy
A. 2
B. 4
C. 1
D. 3

Solution

  1. Step 1: Trace heights and diameter updates for each node.

    Node 4: height=1, diameter=0; Node 2: left=1 (node4), right=0, diameter=max(0,1)=1; Node 3: height=1, diameter=1; Node 1: left=2 (node2), right=1 (node3), diameter=max(1,2+1=3)=3.
  2. Step 2: Verify final diameter value returned.

    The diameter is the maximum sum of left and right heights at any node, which is 3 edges, so the longest path length is 3 edges.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Longest path is from node 4 to node 3 with length 3 edges [OK]
Hint: Diameter counts edges, not nodes [OK]
Common Mistakes:
  • Confusing diameter as number of nodes
  • Off-by-one in height calculation
  • Missing right subtree height
2. You are given a binary tree where each node contains a non-negative integer value. You want to maximize the sum of values you can collect by selecting nodes such that no two directly connected nodes (parent-child) are both selected. Which approach guarantees an optimal solution for this problem?
easy
A. Use a greedy algorithm that always picks the node with the highest value first.
B. Use a depth-first search with dynamic programming that returns two values per node: max if robbing it and max if not robbing it.
C. Use a breadth-first search to select nodes level by level, picking the maximum values at alternate levels.
D. Use a brute force recursion that tries all subsets of nodes without any memoization.

Solution

  1. Step 1: Understand the problem constraints

    The problem requires selecting nodes in a tree such that no parent and child are both selected, maximizing the sum of selected nodes.
  2. Step 2: Identify the suitable algorithmic pattern

    A greedy or BFS level-based approach fails because the tree structure and adjacency constraints are complex. Brute force is correct but inefficient. The optimal solution uses DFS with DP returning two values per node: max if robbing it and max if not robbing it, ensuring all subproblems are solved optimally.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    DFS with two-value DP handles adjacency constraints correctly [OK]
Hint: Tree + no adjacent nodes -> DFS with two-value DP [OK]
Common Mistakes:
  • Assuming greedy or level-based selection works
  • Trying brute force without memoization
3. You are given a binary tree and need to determine if it is a mirror of itself (i.e., symmetric around its center). Which approach guarantees an optimal solution that efficiently checks this property by comparing nodes in a mirrored fashion?
easy
A. Use a recursive DFS that simultaneously compares the left subtree of one node with the right subtree of the other node, returning false immediately on mismatch.
B. Perform a level-order traversal and compare nodes at each level from left to right.
C. Traverse the tree in preorder and check if the sequence of node values is a palindrome.
D. Use a brute force approach that generates all subtree permutations and checks for symmetry.

Solution

  1. Step 1: Understand the problem requires mirrored subtree comparison

    The problem asks if the tree is symmetric, meaning the left subtree is a mirror reflection of the right subtree.
  2. Step 2: Identify the approach that compares mirrored nodes recursively with early exit

    The recursive DFS approach compares left subtree nodes with right subtree nodes in mirrored positions and returns false immediately if any mismatch is found, ensuring efficiency.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Mirrored recursive DFS matches problem requirements [OK]
Hint: Symmetry requires mirrored subtree comparison [OK]
Common Mistakes:
  • Assuming preorder traversal palindrome check works
  • Using level-order traversal without mirrored comparison
  • Trying brute force subtree permutations
4. The following code attempts to count nodes in a complete binary tree using the optimal approach. Identify the line containing the subtle bug that can cause incorrect counts for incomplete last levels.
def exists(idx, h, root):
    left, right = 0, 2**(h - 1) - 1
    for _ in range(h - 1):
        mid = (left + right) // 2
        if idx < mid:  # Bug here
            root = root.left
            right = mid
        else:
            root = root.right
            left = mid + 1
    return root is not null
medium
A. Line with 'if idx < mid:'
B. Line with 'return root is not null'
C. Line with 'root = root.right'
D. Line with 'left, right = 0, 2**(h - 1) - 1'

Solution

  1. Step 1: Understand binary search condition

    The condition should be 'if idx <= mid' to correctly include mid index in left subtree.
  2. Step 2: Identify impact of bug

    Using 'idx < mid' excludes mid index from left subtree, causing incorrect traversal and wrong node existence checks.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Correct binary search must include mid index [OK]
Hint: Binary search must use <= to include mid index [OK]
Common Mistakes:
  • Using < instead of <= in binary search condition
5. What is the time complexity of the parent pointer + ancestor set approach for finding the Lowest Common Ancestor in a binary tree with n nodes and height h?
medium
A. O(h^2) because ancestor set lookups take O(h) each and we do up to h lookups
B. O(n^2) because each node's parent is checked multiple times
C. O(n) to build parent map plus O(h) to find LCA, total O(n)
D. O(n log n) due to sorting ancestors before comparison

Solution

  1. Step 1: Identify parent map construction cost

    Building the parent map requires visiting each node once, O(n).
  2. Step 2: Analyze ancestor set and LCA search

    Ancestor set insertion and lookup are O(1) average. Traversing up to height h for p and q is O(h). Total is O(n) + O(h) ≈ O(n).
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Parent map O(n) + ancestor lookup O(h) = O(n) total [OK]
Hint: Parent map build dominates; ancestor lookup is O(h) [OK]
Common Mistakes:
  • Confusing ancestor set lookup as O(h)
  • Assuming sorting ancestors needed
  • Overestimating repeated parent checks