Knowledge Guide
HomeDSATrees

medium Bottom View Of the Binary Tree

Problem Statement

Given the root of a binary tree, return an array that contains the nodes visible when looking at the tree from the bottom.

The bottom view is formed by collecting the nodes that would be visible if you were to stand directly beneath the tree and look up. If multiple nodes are aligned vertically, only the node at the deepest level should be included in the view.

Examples

Example 1

Image
Image

Example 2

Image
Image

Example 3

Image
Image

Try it yourself

Try solving this question here:

✅ Solution Bottom View Of the Binary Tree

Problem Statement

Given the root of a binary tree, return an array that contains the nodes visible when looking at the tree from the bottom.

The bottom view is formed by collecting the nodes that would be visible if you were to stand directly beneath the tree and look up. If multiple nodes are aligned vertically, only the node at the deepest level should be included in the view.

Examples

Example 1

  • Input: root = [1, 2, 3]
  • Expected Output: [2, 1, 3]
Image
Image
  • Justification: From the bottom view, nodes 2, 1, and 3 are visible because they appear at the lowest vertical and horizontal positions.

Example 2

  • Input: root = [1, 2, 3, 4, null, 5, 6]
  • Expected Output: [4, 2, 5, 3, 6]
Image
Image
  • Justification: Nodes 4, 2, 5, 3, and 6 form the bottom view when observed from below. Each node is at its lowest level compared to any nodes that share the same vertical position.

Example 3

  • Input: root = [10, 7, 4, null, 9, 6, 11]
  • Expected Output: [7, 6, 4, 11]
Image
Image
  • Justification: In this case, 7, 6, 4, and 11 are the nodes visible from the bottom as they are the deepest nodes at their respective vertical positions.

Solution

To solve this problem, we will use the Breadth-First Search (BFS) approach. BFS is ideal because we need to traverse the tree level by level and keep track of the horizontal distance of each node. The bottom view of the binary tree is essentially the last node encountered at each horizontal distance. We will use a queue to perform BFS and a map (or dictionary) to store the last node seen at each horizontal distance. The key in the map will be the horizontal distance, and the value will be the node's value. At the end, we will sort the keys of the map and return the corresponding values as the bottom view.

This approach works well because BFS ensures that we explore each level of the tree systematically, and the map allows us to efficiently overwrite nodes at the same horizontal distance with the deeper node when necessary.

Step-by-step Algorithm

  1. Check if the root is null:

    • If the root is null, return an empty list since there is no tree to process.
  2. Initialize a map:

    • Create a Map<Integer, Integer> to store the bottom view of the tree. The key of the map will be the horizontal distance (HD) of the node, and the value will be the node's value. This will help us track the deepest node at each horizontal distance.
  3. Initialize a queue:

    • Create a Queue<Pair<TreeNode, Integer>>. Each element of the queue is a pair containing:
      • A reference to a TreeNode.
      • The node's horizontal distance.
    • The queue is used for Breadth-First Search (BFS), ensuring we explore the tree level by level.
    • Add the root node to the queue with a horizontal distance of 0 (i.e., queue.add(new Pair<>(root, 0))).
  4. Perform BFS traversal:

    • While the queue is not empty:
      1. Dequeue the front element:
        • Remove the front element from the queue. This gives us a node and its horizontal distance.
      2. Update the map:
        • Insert or update the map with the current node's value at the corresponding horizontal distance. If there is already a value for that horizontal distance, it gets overwritten since we are updating with the node at the deepest level.
      3. Check if the node has a left child:
        • If the current node has a left child, add the left child to the queue with a horizontal distance that is one less than the current node's (i.e., hd - 1).
      4. Check if the node has a right child:
        • If the current node has a right child, add the right child to the queue with a horizontal distance that is one more than the current node's (i.e., hd + 1).
  5. Extract the bottom view:

    • After the BFS traversal is complete, the map will contain the bottom-most node for each horizontal distance.
    • Sort the keys (horizontal distances) in the map.
    • Traverse the sorted keys and add the corresponding node values to the result list.
  6. Return the result:

    • Return the list of node values as the bottom view of the tree.

Algorithm Walkthrough

Input: root = [10, 7, 4, null, 9, 6, 11]

  • Initial Tree Structure:

            10
           /  \
          7    4
           \   / \
           9  6  11
    
  • Step-by-Step Walkthrough:

  1. Initialize the queue and map:

    • Queue: [(10, 0)] (Root node with HD = 0)
    • Map: {} (Empty at the start)
  2. Process node 10 (HD = 0):

    • Dequeue 10 with HD = 0.
    • Add 10 to the map: {0: 10}.
    • Add its left child 7 to the queue with HD = -1.
    • Add its right child 4 to the queue with HD = 1.
    • Queue: [(7, -1), (4, 1)].
  3. Process node 7 (HD = -1):

    • Dequeue 7 with HD = -1.
    • Add 7 to the map: {-1: 7, 0: 10}.
    • 7 has no left child, so nothing is added for the left side.
    • Add its right child 9 to the queue with HD = 0 (HD of 7 + 1).
    • Queue: [(4, 1), (9, 0)].
  4. Process node 4 (HD = 1):

    • Dequeue 4 with HD = 1.
    • Add 4 to the map: {-1: 7, 0: 10, 1: 4}.
    • Add its left child 6 to the queue with HD = 0.
    • Add its right child 11 to the queue with HD = 2.
    • Queue: [(9, 0), (6, 0), (11, 2)].
  5. Process node 9 (HD = 0):

    • Dequeue 9 with HD = 0.
    • Update the map at HD 0: {-1: 7, 0: 9, 1: 4} (since 9 is deeper than 10).
    • 9 has no children, so nothing is added to the queue.
    • Queue: [(6, 0), (11, 2)].
  6. Process node 6 (HD = 0):

    • Dequeue 6 with HD = 0.
    • Update the map at HD 0: {-1: 7, 0: 6, 1: 4} (since 6 is deeper than 9).
    • 6 has no children, so nothing is added to the queue.
    • Queue: [(11, 2)].
  7. Process node 11 (HD = 2):

    • Dequeue 11 with HD = 2.
    • Add 11 to the map: {-1: 7, 0: 6, 1: 4, 2: 11}.
    • 11 has no children, so nothing is added to the queue.
    • Queue is now empty.
  8. Final Step - Extract Bottom View:

    • The map contains: {-1: 7, 0: 6, 1: 4, 2: 11}.
    • The sorted horizontal distances are: -1, 0, 1, 2.
    • The corresponding bottom view is: [7, 6, 4, 11].

Code

java
import java.util.*;

// class TreeNode {
//     int val;
//     TreeNode left, right;
//     TreeNode(int val) {
//         this.val = val;
//         this.left = null;
//         this.right = null;
//     }
// }

class Pair<K, V> {

  private K key;
  private V value;

  public Pair(K key, V value) {
    this.key = key;
    this.value = value;
  }

  public K getKey() {
    return key;
  }

  public V getValue() {
    return value;
  }
}

public class Solution {

  public List<Integer> bottomView(TreeNode root) {
    // Initialize result list to store bottom view nodes
    List<Integer> result = new ArrayList<>();

    // Return empty list if tree is empty
    if (root == null) return result;

    // Map to store the bottom view: horizontal distance -> node value
    Map<Integer, Integer> map = new TreeMap<>();

    // Queue to perform BFS, stores pairs of node and its horizontal distance
    Queue<Pair<TreeNode, Integer>> queue = new LinkedList<>();

    // Start BFS with root node at horizontal distance 0
    queue.add(new Pair<>(root, 0));

    while (!queue.isEmpty()) {
      // Get the current node and its horizontal distance
      Pair<TreeNode, Integer> current = queue.poll();
      TreeNode node = current.getKey();
      int hd = current.getValue();

      // Update the map with the current node at its horizontal distance
      map.put(hd, node.val);

      // If left child exists, add to queue with horizontal distance - 1
      if (node.left != null) queue.add(new Pair<>(node.left, hd - 1));

      // If right child exists, add to queue with horizontal distance + 1
      if (node.right != null) queue.add(new Pair<>(node.right, hd + 1));
    }

    // Add the nodes from the map to the result list in order of horizontal distance
    for (int value : map.values()) {
      result.add(value);
    }

    return result;
  }

  public static void main(String[] args) {
    Solution sol = new Solution();

    // Test Example 1: root = [1, 2, 3]
    TreeNode root1 = new TreeNode(1);
    root1.left = new TreeNode(2);
    root1.right = new TreeNode(3);
    System.out.println(sol.bottomView(root1)); // Expected Output: [2, 1, 3]

    // Test Example 2: root = [1, 2, 3, 4, null, 5, 6]
    TreeNode root2 = new TreeNode(1);
    root2.left = new TreeNode(2);
    root2.right = new TreeNode(3);
    root2.left.left = new TreeNode(4);
    root2.right.left = new TreeNode(5);
    root2.right.right = new TreeNode(6);
    System.out.println(sol.bottomView(root2)); // Expected Output: [4, 2, 5, 3, 6]

    // Test Example 3: root = [10, 7, 4, null, 9, 6, 11]
    TreeNode root3 = new TreeNode(10);
    root3.left = new TreeNode(7);
    root3.right = new TreeNode(4);
    root3.left.right = new TreeNode(9);
    root3.right.left = new TreeNode(6);
    root3.right.right = new TreeNode(11);
    System.out.println(sol.bottomView(root3)); // Expected Output: [7, 6, 4, 11]
  }
}

Complexity Analysis

Time Complexity

  • The time complexity of the algorithm is , where N is the number of nodes in the binary tree. This is because we are traversing each node once using BFS (level order traversal).
  • Accessing and updating the Map to maintain nodes at different horizontal distances takes time

So, the overall time complexity is .

Space Complexity

  • The space complexity of the algorithm is . This includes:
    • The queue used for BFS traversal, which in the worst case can contain nodes.
    • The Map that stores nodes at different horizontal distances. In the worst case, the tree can be completely skewed, which means the number of unique horizontal distances will also be .
🤖 Don't fully get this? Learn it with Claude

Stuck on Bottom View Of the Binary Tree? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🪜 Hint ladder (no spoilers)

Progressively stronger hints — you still solve it.

I'm working on the problem **Bottom View Of the Binary Tree** (DSA). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🎨 Explain the approach visually

See the technique, not just code.

Explain the optimal approach to **Bottom View Of the Binary Tree** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔍 Review my solution

Catch bugs, edge cases, sub-optimality.

I'll paste my solution to **Bottom View Of the Binary Tree**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔁 Drill the pattern

Lock in recognition with look-alikes.

Give me 2 problems that use the SAME underlying pattern as **Bottom View Of the Binary Tree**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes