0
0
DSA Typescriptprogramming

Check if Binary Tree is Balanced in DSA Typescript

Choose your learning style9 modes available
Mental Model
A balanced binary tree means no branch is much longer than another. We check if every node's left and right branches differ in height by at most one.
Analogy: Imagine a tree with branches. If one branch is much longer than its sibling, the tree looks lopsided and might fall. We want to make sure all branches grow evenly.
      1
     / \
    2   3
   / 
  4  

Balanced tree example: left and right heights differ by at most 1.
Dry Run Walkthrough
Input: Binary tree: 1 with left child 2, right child 3; 2 has left child 4
Goal: Determine if the tree is balanced by checking height differences at each node
Step 1: Check height of node 4 (leaf)
Node 4 height = 0 (no children)
Why: Leaf nodes have height 0, base case for height calculation
Step 2: Check height of node 2: left height = 0 (node 4), right height = -1 (no right child)
Height difference at node 2 = 1 (0 - (-1))
Why: Difference 1 is allowed, so node 2 is balanced
Step 3: Check height of node 3 (leaf)
Node 3 height = 0
Why: Leaf node height is 0
Step 4: Check height of root node 1: left height = 1 (node 2), right height = 0 (node 3)
Height difference at node 1 = 1 (1 - 0)
Why: Difference 1 is allowed, so root is balanced
Step 5: Since all nodes are balanced, return true
Tree is balanced
Why: No node violates the height difference rule
Result:
1
/ \
2   3
/ 
4

Balanced: true
Annotated Code
DSA Typescript
class TreeNode {
  val: number;
  left: TreeNode | null;
  right: TreeNode | null;
  constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
    this.val = val === undefined ? 0 : val;
    this.left = left === undefined ? null : left;
    this.right = right === undefined ? null : right;
  }
}

function isBalanced(root: TreeNode | null): boolean {
  function checkHeight(node: TreeNode | null): number {
    if (node === null) return -1; // base case: empty subtree height

    const leftHeight = checkHeight(node.left); // get left subtree height
    if (leftHeight === Number.MIN_SAFE_INTEGER) return Number.MIN_SAFE_INTEGER; // left subtree unbalanced

    const rightHeight = checkHeight(node.right); // get right subtree height
    if (rightHeight === Number.MIN_SAFE_INTEGER) return Number.MIN_SAFE_INTEGER; // right subtree unbalanced

    if (Math.abs(leftHeight - rightHeight) > 1) return Number.MIN_SAFE_INTEGER; // current node unbalanced

    return Math.max(leftHeight, rightHeight) + 1; // height of current node
  }

  return checkHeight(root) !== Number.MIN_SAFE_INTEGER;
}

// Driver code
const root = new TreeNode(1,
  new TreeNode(2, new TreeNode(4), null),
  new TreeNode(3)
);

console.log(isBalanced(root));
if (node === null) return -1; // base case: empty subtree height
return -1 height for empty subtree to count edges correctly
const leftHeight = checkHeight(node.left);
recursively get left subtree height
if (leftHeight === Number.MIN_SAFE_INTEGER) return Number.MIN_SAFE_INTEGER;
propagate unbalanced signal up if left subtree unbalanced
const rightHeight = checkHeight(node.right);
recursively get right subtree height
if (rightHeight === Number.MIN_SAFE_INTEGER) return Number.MIN_SAFE_INTEGER;
propagate unbalanced signal up if right subtree unbalanced
if (Math.abs(leftHeight - rightHeight) > 1) return Number.MIN_SAFE_INTEGER;
detect unbalanced node by height difference > 1
return Math.max(leftHeight, rightHeight) + 1;
return height of current node as max child height + 1
return checkHeight(root) !== Number.MIN_SAFE_INTEGER;
final check: if unbalanced signal not found, tree is balanced
OutputSuccess
true
Complexity Analysis
Time: O(n) because we visit each node once to calculate heights and check balance
Space: O(h) where h is tree height due to recursion stack
vs Alternative: Naive approach recalculates heights repeatedly causing O(n^2) time; this method calculates height and balance in one pass for O(n) time
Edge Cases
Empty tree (root is null)
Returns true because empty tree is balanced
DSA Typescript
if (node === null) return -1;
Single node tree
Returns true because single node has no imbalance
DSA Typescript
if (node === null) return -1;
Unbalanced tree with one branch much deeper
Returns false when height difference > 1 detected
DSA Typescript
if (Math.abs(leftHeight - rightHeight) > 1) return Number.MIN_SAFE_INTEGER;
When to Use This Pattern
When you need to check if a tree is balanced, use a bottom-up height check with early stopping to detect imbalance efficiently.
Common Mistakes
Mistake: Calculating height separately from balance check causing repeated work
Fix: Combine height calculation and balance check in one recursive function with early return
Mistake: Returning 0 for null nodes instead of -1, causing off-by-one height errors
Fix: Return -1 for null nodes to count edges correctly in height
Summary
Checks if a binary tree is balanced by ensuring height difference between left and right subtrees is at most one at every node.
Use when you want to verify tree balance to optimize operations like search or insert.
The key insight is to calculate height and check balance in one pass, returning a special value to stop early if unbalanced.