Grokking Tree Coding Patterns for Interviews
Ask Author
Back to course home

0% completed

Vote For New Content
Solution: Bottom View Of the Binary Tree
Table of Contents

Contents are not accessible

Contents are not accessible

Contents are not accessible

Contents are not accessible

Contents are not accessible

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
  • 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
  • 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
  • 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

Python3
Python3

. . . .

Complexity Analysis

Time Complexity

  • The time complexity of the algorithm is O(N), 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 O(1) time

So, the overall time complexity is O(N).

Space Complexity

  • The space complexity of the algorithm is O(N). This includes:
    • The queue used for BFS traversal, which in the worst case can contain O(N) 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 O(N).

.....

.....

.....

Like the course? Get enrolled and start learning!

Table of Contents

Contents are not accessible

Contents are not accessible

Contents are not accessible

Contents are not accessible

Contents are not accessible