Find Minimum Depth of Binary Tree

Difficulty: Easy, Asked-in: Facebook, Amazon.

Key takeaway: An excellent problem to learn problem-solving using both recursive and iterative tree traversal. This is also a question to understand efficient problem solving using BFS when the solution node is nearest to the root node.

Let's understand the problem!

Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node. The path has to end on a leaf node.

Example

Min depth of binary tree example

Discussed solution approaches

  • Using depth-first Search: Recursive tree traversal
  • Using breadth-first search: Iterative tree traversal

Using depth-first search: Recursive tree traversal

Solution idea and steps

We can find the solution by solving the two smaller subproblems: finding the minimum depth of the left subtree and finding the minimum depth of the right subtree. Here's an idea: If we know the minimum depth of both the left and right subtrees, then the minimum depth of the entire tree = 1 + min (min depth of the left subtree, min depth of the right subtree).

  • Suppose function treeMinDepth(root) will return the value of the min-depth of the overall tree.
  • if(root == NULL), return 0. This is the base case which is the smallest version of the problem where recursion will backtrack and return the value directly.
  • if(root->left == NULL): we recursively call the same function for the right subtree and calculate the min-depth. In other words, there is no left sub-tree and min-depth of the tree = 1 + min-depth of the right subtree. treeMinDepth(root) = 1 + treeMinDepth(root->right).
  • if(root->right == NULL): we recursively call the same function for the left subtree and calculate the min-depth i.e. there is no right sub-tree and min-depth of the tree = 1 + min-depth of the left subtree. treeMinDepth(root) = 1 + treeMinDepth(root->left).
  • If both children are not NULL: we recursively call the same function for the left and right subtree, calculate the min-depth and get minimum of both to calculate the min-depth of the overall tree. treeMinDepth(root) = 1 + min (treeMinDepth(root->left), treeMinDepth(root->right)).

Solution code C++

int treeMinDepth(TreeNode* root)
{
    if(root == NULL)
        return 0;
        
    if(root->left == NULL)
        return 1 + treeMinDepth(root->right);
        
    if(root->right == NULL)
        return 1 + treeMinDepth(root->left);
        
    return 1 + min(treeMinDepth(root->left), treeMinDepth(root->right));    
}

Solution code Python

def treeMinDepth(root):
    if root is None:
        return 0
    
    if root.left is None:
        return 1 + treeMinDepth(root.right)
    
    if root.right is None:
        return 1 + treeMinDepth(root.left)
    
    return 1 + min(treeMinDepth(root.left), treeMinDepth(root.right))

Solution code Java

class BinaryTreeMinDepth 
{
    public int treeMinDepth(TreeNode root) 
    {
        if (root == null)
            return 0;

        if (root.left == null)
            return 1 + treeMinDepth(root.right);

        if (root.right == null)
            return 1 + treeMinDepth(root.left);

        return 1 + Math.min(treeMinDepth(root.left), treeMinDepth(root.right));
    }
}

Time and space complexity analysis

We are traversing each node of the tree only once. Time complexity = O(n)

Space complexity = O(h) for recursion call stack. Space complexity is equal to the maximum depth of the recursion tree which is equal to the height of the tree (h), where O(log n) < h < O(n).

Using breadth-first search: Iterative tree traversal

Solution idea

Now, critical questions are: Can we solve this problem iteratively using BFS traversal? How do we calculate the minimum depth using this idea? Or do we really need to calculate the minimum depth for each node? Is there some hidden information in the problem that could help us solve it efficiently? Let's think!

Here is an observation: The node with the minimum depth will always be the first leaf node if we traverse the tree level by level. In other words, when traversing the tree level by level, we only need to return the depth of the first encountered leaf node.

In a practical scenario, this idea would be much more efficient compared to the DFS approach because, in the DFS approach, we may end up traversing the entire tree even when the topmost leaf is close to the root. However, in BFS traversal, we can access the nodes from top to bottom in level order, which will help us quickly find the topmost leaf node in fewer steps.

For example, suppose we have a tree where the left subtree has a depth of 100 and the right subtree has a depth of 1. With DFS, we would first traverse all the 100 nodes in the left subtree before finally reaching the right subtree with a depth of 1 and identifying it as the minimum depth. However, with BFS, instead of traversing 101 nodes to determine the minimum depth, we can obtain the value in just two steps. Now, imagine the difference in efficiency when dealing with thousands of nodes in the left subtree!

Solution code C++

int treeMinDepth(TreeNode* root) 
{
    if (root == NULL)
        return 0;
    
    queue<pair<TreeNode*, int>> q;
    q.push({root, 1});

    while (q.empty() == false) 
    {
        TreeNode* temp = q.front().first;
        int depth = q.front().second;
        q.pop();

        if (temp->left == NULL && temp->right == NULL)
            return depth;
        else 
        {
            if (temp->left != NULL)
                q.push({temp->left, depth + 1});

            if (temp->right != NULL)
                q.push({temp->right, depth + 1});
        }
    }

    return 0;
}

Solution code Python

def treeMinDepth(root):
    if root is None:
        return 0
    
    q = Queue()
    q.put((root, 1))

    while not q.empty():
        temp, depth = q.get()

        if temp.left is None and temp.right is None:
            return depth
        else:
            if temp.left is not None:
                q.put((temp.left, depth + 1))

            if temp.right is not None:
                q.put((temp.right, depth + 1))

    return 0

Solution code Java

class BinaryTreeMinDepth 
{
    static class NodeWithDepth 
    {
        TreeNode node;
        int depth;

        NodeWithDepth(TreeNode node, int depth) 
        {
            this.node = node;
            this.depth = depth;
        }
    }

    public static int treeMinDepth(TreeNode root) 
    {
        if (root == null)
            return 0;

        Queue<NodeWithDepth> queue = new LinkedList<>();
        queue.add(new NodeWithDepth(root, 1));

        while (queue.isEmpty() == false) 
        {
            NodeWithDepth nodeWithDepth = queue.poll();
            TreeNode temp = nodeWithDepth.node;
            int depth = nodeWithDepth.depth;

            if (temp.left == null && temp.right == null)
                return depth;
            else 
            {
                if (temp.left != null)
                    queue.add(new NodeWithDepth(temp.left, depth + 1));

                if (temp.right != null)
                    queue.add(new NodeWithDepth(temp.right, depth + 1));
            }
        }

        return 0;
    }
}

Time and space complexity analysis

In the worst case, the total number of queue operations = 2n, because each node gets inserted and deleted only once in BFS traversal. So time complexity = O(n), where n is the total number of nodes. Space complexity = O(w) because BFS traversal requires queue size proportional to the max-width of the tree (w).

Critical ideas to think!

  • Why do we need a queue data structure in the level-order traversal?
  • What is the worst-case and best-case space complexity in the BFS approach?
  • Can we solve this problem using all DFS traversals?
  • Why do we prefer BFS when the solution node is closer to the root? In which scenario do we prefer the DFS approach?
  • Can we implement the BFS approach without using a tuple or pair?

Suggested coding problems to practice

  • Max depth of the binary tree
  • Find the diameter of a binary tree
  • Count all leaf nodes in a binary tree
  • Root to leaf paths with the sum
  • Count all nodes with one child
  • Depth of the deepest odd level node

Enjoy learning, Enjoy coding, Enjoy problem-solving!

More from EnjoyAlgorithms

Self-paced Courses and Blogs