Height of a Binary Tree

Hero Image

Problem Overview

The LeetCode problem "Maximum Depth of Binary Tree" is a classic problem that involves determining the depth or height of a binary tree. The depth of a binary tree is the number of nodes along the longest path from the root node down to the farthest leaf node.

Given the root of a binary tree, the task is to find its maximum depth.

Understanding the Problem

The essence of the problem is rooted in understanding tree structure. Binary trees are hierarchical, with each node having at most two children known as the left and right child. The challenge here is to traverse the tree effectively to calculate the longest path from the root node to any leaf node.

Consider a binary tree like this:

        1
       / \
      2   3
     / \
    4   5

The maximum depth of this tree is 3, namely: the path 1 -> 2 -> 4 (or equivalently, 1 -> 2 -> 5).

Key DSA Concepts and Theory

Trees

A tree is a data structure composed of nodes. The topmost node is called the root node, and each node contains some data and references to other nodes (children). Binary trees restrict each node to having no more than two children.

Recursion

Recursion is a fundamental approach often employed to traverse binary trees. Recursive methods involve a function calling itself with a subset of the original data until the base case is met.

Depth-First Search (DFS)

DFS is a traversal method used to explore nodes and children before visiting siblings. There are three types of DFS traversals:

  • Preorder (Node -> Left -> Right)
  • Inorder (Left -> Node -> Right)
  • Postorder (Left -> Right -> Node)

Depth calculation typically uses a form of DFS, often postorder, since it allows you to compute properties of a node after ensuring properties are computed for both children.

Solution Approach

To determine the maximum depth of a binary tree, we utilize a recursive strategy leveraging Depth-First Search. The approach involves:

  1. Base Case: If the current node is null, return a depth of 0.
  2. Recursive Case: Compute the maximum depth of the left subtree and right subtree.
  3. The depth of the current node is 1 + max(depth of left subtree, depth of right subtree).

This ensures that each recursive call handles part of the tree and contributes to the final depth calculation.

C++ Implementation

class Solution {
public:
    int maxDepth(TreeNode* root) {
        if (root == nullptr) {
            return 0;
        }
        int leftDepth = maxDepth(root->left);
        int rightDepth = maxDepth(root->right);
        return 1 + std::max(leftDepth, rightDepth);
    }
};

Java Implementation

class Solution {
    public int maxDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int leftDepth = maxDepth(root.left);
        int rightDepth = maxDepth(root.right);
        return 1 + Math.max(leftDepth, rightDepth);
    }
}

Time and Space Complexity Analysis

  • Time Complexity: The algorithm visits each node exactly once, resulting in a time complexity of O(N), where N is the number of nodes in the tree.
  • Space Complexity: The space complexity is O(H), where H is the height of the tree, due to the recursive call stack. In the worst-case scenario of an unbalanced tree, this could be as large as O(N).

Common Mistakes to Avoid

  • Failing to handle null values: Always ensure the base case of a null node returning 0 is implemented to prevent null pointer exceptions.
  • Incorrect recursive logic: Ensure you are using max(leftDepth, rightDepth) and not just one of these values.

Similar Problems on LeetCode

  • Minimum Depth of Binary Tree - Problem number 111
  • Balanced Binary Tree - Problem number 110
  • Symmetric Tree - Problem number 101

Additional Resources and References

Understanding these fundamental concepts of tree data structures, recursion, and DFS traversal is crucial for tackling similar problems efficiently.