Balanced Binary Tree

Easytreedepth-first-searchrecursion
Category: Trees
Companies that ask this question:
AmazonFacebookBloombergMicrosoft

Approach

Balanced Binary Tree

Problem Statement

Given a binary tree, determine if it is height-balanced.

A height-balanced binary tree is a binary tree in which the depth of the two subtrees of every node never differs by more than one.

Examples

Example 1

Input: root = [3,9,20,null,null,15,7]
Output: true

Tree:
      3
     / \
    9  20
      /  \
     15   7

Node 3: |height(left) - height(right)| = |1 - 2| = 1 ✓
Node 9: leaf ✓
Node 20: |1 - 1| = 0 ✓
All nodes balanced → tree is balanced

Example 2

Input: root = [1,2,2,3,3,null,null,4,4]
Output: false

Tree:
        1
       / \
      2   2
     / \
    3   3
   / \
  4   4

Node 2: |height(left) - height(right)| = |3 - 1| = 2 ✗
Tree is NOT balanced

Example 3

Input: root = []
Output: true

Intuition

A tree is balanced if:

  1. Left subtree is balanced
  2. Right subtree is balanced
  3. Height difference between left and right ≤ 1

This naturally fits a recursive pattern where we check balance bottom-up.

Pattern Recognition

This is a Tree DFS + Height Calculation problem with:

  • Post-order traversal (check children before parent)
  • Combine two checks: balance status + height
  • Early termination on imbalance

Approach

Optimized: Single Pass DFS

Return two pieces of information from each recursive call:

  1. Is subtree balanced?
  2. Height of subtree

We can encode this efficiently:

  • Return actual height if balanced
  • Return -1 if unbalanced (sentinel value)

Algorithm:

  1. Base Case: Null node is balanced with height 0
  2. Recursive Case:
    • Get left subtree height (or -1 if unbalanced)
    • Get right subtree height (or -1 if unbalanced)
    • If either is -1 → return -1 (propagate imbalance)
    • If |left_height - right_height| > 1 → return -1
    • Otherwise → return 1 + max(left_height, right_height)

Why this works:

  • Single pass through tree
  • Early termination on first imbalance
  • Height calculation is needed anyway

Naive Approach

Calculate height at each node and check difference:

isBalanced(root):
  if not root: return True
  left_height = height(root.left)
  right_height = height(root.right)
  return abs(left_height - right_height) <= 1 and
         isBalanced(root.left) and isBalanced(root.right)

Problem: O(n²) time - recalculates heights

Edge Cases

  • Empty tree → balanced
  • Single node → balanced
  • Skewed tree → unbalanced
  • Perfect tree → balanced
  • Imbalance at any level

Complexity Analysis

  • Time: O(n) where n = number of nodes

    • Visit each node once
    • O(1) work per node
  • Space: O(h) where h = height

    • Recursion call stack
    • O(log n) for balanced, O(n) for skewed

Solution

java
1class TreeNode {
2    int val;
3    TreeNode left;
4    TreeNode right;
5    TreeNode() {}
6    TreeNode(int val) { this.val = val; }
7    TreeNode(int val, TreeNode left, TreeNode right) {
8        this.val = val;
9        this.left = left;
10        this.right = right;
11    }
12}
13
14class Solution {
15    public boolean isBalanced(TreeNode root) {
16        return checkHeight(root) != -1;
17    }
18
19    private int checkHeight(TreeNode node) {
20        // Base case: null node is balanced with height 0
21        if (node == null) {
22            return 0;
23        }
24
25        // Check left subtree
26        int leftHeight = checkHeight(node.left);
27        if (leftHeight == -1) {  // Left subtree unbalanced
28            return -1;
29        }
30
31        // Check right subtree
32        int rightHeight = checkHeight(node.right);
33        if (rightHeight == -1) {  // Right subtree unbalanced
34            return -1;
35        }
36
37        // Check if current node is balanced
38        if (Math.abs(leftHeight - rightHeight) > 1) {
39            return -1;
40        }
41
42        // Return height of current subtree
43        return 1 + Math.max(leftHeight, rightHeight);
44    }
45}
46
Loading visualizer...