Open In App

Bottom View of a Binary Tree

Last Updated : 01 Nov, 2024
Summarize
Comments
Improve
Suggest changes
Like Article
Like
Share
Report
News Follow

Given a binary tree, an array where elements represent the bottom view of the binary tree from left to right.

Note: If there are multiple bottom-most nodes for a horizontal distance from the root, then the latter one in the level traversal is considered.

Examples:

Example1: The Green nodes represent the bottom view of below binary tree.

sum-of-nodes-in-bottom-view-of-binary-tree


Example2: The Green nodes represent the bottom view of below binary tree.

sum-of-nodes-in-bottom-view-of-binary-tree-2

[Expected Approach – 1] Using level order traversal – O(nlogn) Time and O(n) Space

The idea is to perform a level order traversal (BFS) while tracking each node’s horizontal distance (HD) from the root. Starting with the root at HD 0, left children have HD – 1 and right children have HD + 1. We use a queue to process nodes level by level, updating a hashmap with each node’s data at its corresponding HD, ensuring that the last node processed at each HD represents the bottom view. By tracking the minimum and maximum HDs during traversal, we know the full range of HDs. After traversal, we extract nodes from the map in order of their HDs, which gives us the bottom view of the tree as seen from directly below.

Below is the implementation of the above approach:

C++
// C++ code to find the bottom view 
// using level-order traversal
#include <bits/stdc++.h>
using namespace std;

class Node {
public:
    int data;
    Node *left, *right;

    Node(int x) {
        data = x;
        left = right = nullptr;
    }
};

// Function to return the bottom view 
// of the binary tree
vector<int> bottomView(Node *root) {
    if (!root) return {};

    // Map to store the last node at each 
    // horizontal distance (HD)
    map<int, int> hdMap;
    
    // Queue to store nodes and their HD
    queue<pair<Node*, int>> q;
    
    // Start level order traversal with
      // root at HD 0
    q.push({root, 0});
    
    while (!q.empty()) {
      
        // Get current node and its HD
        Node *curr = q.front().first;
        int hd = q.front().second;
        q.pop();
        
        // Update the map with the current
          // node's data
        hdMap[hd] = curr->data;
        
        // Traverse the left subtree, HD - 1
        if (curr->left) {
            q.push({curr->left, hd - 1});
        }
        
        // Traverse the right subtree, HD + 1
        if (curr->right) {
            q.push({curr->right, hd + 1});
        }
    }
    
    // Extract bottom view nodes 
      // from the map
    vector<int> result;
    
    // Iterate through the map in 
      // sorted HD order
    for (auto it : hdMap) {
        result.push_back(it.second);
    }
    
    return result;
}

void printArray(vector<int>& arr) {
    
    cout << endl;
}

int main() {
  
    // Representation of the input tree:
    //       20
    //      /  \
    //     8   22
    //    / \    \
    //   5   3   25
    //      / \
    //     10 14
    Node *root = new Node(20);
    root->left = new Node(8);
    root->right = new Node(22);
    root->left->left = new Node(5);
    root->left->right = new Node(3);
    root->left->right->left = new Node(10);
    root->left->right->right = new Node(14);
    root->right->right = new Node(25);

    vector<int> result = bottomView(root);
    for (int val : result) {
        cout << val << " ";
    }
    
    return 0;
}
Java Python C# JavaScript

Output
5 10 3 14 25 

[Expected Approach – 2] Using Depth first search – O(nlogn) Time and O(n) Space

Create a hashmap where the key is the horizontal distance and the value is a pair(a, b) where a is the value of the node and b is the height of the node. Perform a pre-order traversal of the tree. If the current node at a horizontal distance of h is the first seen, insert it into the map. Otherwise, compare the node with the existing one in map and if the height of the new node is greater, update the Map.

Below is the implementation of the above approach:

C++
// C++ code to find the bottom view 
// using depth-first search (DFS)
#include <bits/stdc++.h>
using namespace std;

struct Node {
    int data;
    Node *left, *right;

    Node(int x) {
        data = x;
        left = right = nullptr;
    }
};

// Helper function to perform DFS and 
// update the bottom view
void dfs(Node* root, int hd, int depth, 
            map<int, pair<int, int>>& hdMap) {
    if (!root) return;

    // If this horizontal distance is  
    // being visited for the first time or 
    // we're at a deeper level, update it
    if (hdMap.find(hd) == hdMap.end() 
                      || depth >= hdMap[hd].second) {
        hdMap[hd] = {root->data, depth};
    }

    // Traverse the left subtree with 
    // HD - 1 and increased depth
    dfs(root->left, hd - 1, depth + 1, hdMap);

    // Traverse the right subtree with 
    // HD + 1 and increased depth
    dfs(root->right, hd + 1, depth + 1, hdMap);
}

// Function to return the bottom view 
// of the binary tree using DFS
vector<int> bottomView(Node *root) {
    if (!root) return {};

    // Map to store the last node's data and its depth
    // at each horizontal distance (HD)
    map<int, pair<int, int>> hdMap;

    // Start DFS with root at HD 0 and depth 0
    dfs(root, 0, 0, hdMap);
    
    // Extract bottom view nodes from the map
    vector<int> result;

    // Iterate through the map in 
      // sorted HD order
    for (auto it : hdMap) {
        result.push_back(it.second.first);
    }
    
    return result;
}


int main() {
  
    // Representation of the input tree:
    //       20
    //      /  \
    //     8   22
    //    / \    \
    //   5   3   25
    //      / \
    //     10 14
    Node *root = new Node(20);
    root->left = new Node(8);
    root->right = new Node(22);
    root->left->left = new Node(5);
    root->left->right = new Node(3);
    root->left->right->left = new Node(10);
    root->left->right->right = new Node(14);
    root->right->right = new Node(25);

    vector<int> result = bottomView(root);
    for (int val : result) {
        cout << val << " ";
    }
    
    
    return 0;
}
Java Python C# JavaScript

Output
5 10 3 14 25 

[Alternate Approach] Using Hashing – O(n) Time and O(n) Space

Note : This solution might not give output nodes in any specific order.

The idea is to create a hashmap where the key is the horizontal distance and the value is a int x, where x is the value of the node. Perform a level order traversal of the tree. For every node at a horizontal distance of h we will store its value in map.


Below is the implementation of the above approach:

C++
// C++ code to find the bottom view using 
// hashmap
#include <bits/stdc++.h>
using namespace std;

struct Node {
    int data;
    Node *left, *right;

    Node(int x) {
        data = x;
        left = right = nullptr;
    }
};

// Function to return the bottom view of 
// the binary tree
vector<int> bottomView(Node *root) {

    // if root is NULL, return empty vector
    if (!root) return {};

    // Unordered map to store <vertical_index,
    // root->data>
    unordered_map<int, int> hash;

    // Store the leftmost index to help in 
    // left-to-right traversal
    int leftmost = 0;

    // Queue for level order traversal with 
    // pair<Node*, vertical index>
    queue<pair<Node*, int>> q;
    
    // Push the root with vertical index 0
    q.push({root, 0});

    while (!q.empty()) {

        // Store q.front() in top variable
        auto top = q.front();
        q.pop();

        // Current node
        Node *curr = top.first;
        
        // Vertical index of the current node
        int ind = top.second;

        // Update the vertical index -> node data
        hash[ind] = curr->data;

        // Track the leftmost vertical index
        leftmost = min(ind, leftmost);

        // Traverse left child with vertical 
          // index ind - 1
        if (curr->left) { 
            q.push({curr->left, ind - 1});
        }
        
        // Traverse right child with vertical 
          // index ind + 1
        if (curr->right) { 
            q.push({curr->right, ind + 1});
        }
    }

    // Vector to store the final bottom view
    vector<int> ans;

    // Traverse each value in hash from 
    // leftmost to rightmost
    while (hash.find(leftmost) != hash.end()) {
        ans.push_back(hash[leftmost++]);
    }

    return ans;
}


int main() {
  
    // Representation of the input tree:
    //       20
    //      /  \
    //     8   22
    //    / \    \
    //   5   3   25
    //      / \
    //     10 14
    Node *root = new Node(20);
    root->left = new Node(8);
    root->right = new Node(22);
    root->left->left = new Node(5);
    root->left->right = new Node(3);
    root->left->right->left = new Node(10);
    root->left->right->right = new Node(14);
    root->right->right = new Node(25);

    vector<int> result = bottomView(root);

    for (int val : result) {
        cout << val << " ";
    }

    return 0;
}
Java Python C# JavaScript

Output
5 10 3 14 25 




Next Article

Similar Reads

three90RightbarBannerImg