Given the root of a binary tree, find the bottom view of the tree as a list of node values in order of increasing horizontal distance(HD).
The root has HD = 0.
The left child decreases HD by 1, and the right child increases HD by 1.
If multiple nodes share the same HD and depth, select the node that appears later in level-order traversal.
Return the values of these nodes from the leftmost to the rightmost horizontal distance.
Examples:
Input:
Output: [4, 2, 5, 3, 6] Explanation:
Input:
Output: [5, 10, 4, 28, 25] Explanation: Here, 14 and 28 both have horizontal distance = 1 from root, but we are taking 28 in our answer as 28 appears later in the level order traversal.
[Expected Approach - 1] Using DFS - O(n) Time and O(n) Space
The idea is to create a hashmap to store the horizontal distance and the bottom-most node having that horizontal distance wrt root node. During DFS, if we encounter a node whose horizontal distance is not present in the map, add it to the map. If we encounter a node whose horizontal distance already exists as a key in the map:
Choose the node with greater depth.
If both nodes have the same depth, choose the current node, because it appears later in level order traversal.
C++
#include<iostream>#include<vector>#include<unordered_map>usingnamespacestd;// Node StructureclassNode{public:intdata;Node*left;Node*right;Node(intx){data=x;left=right=NULL;}};intminHD,maxHD;// DFS function to fill hdMap with bottom-most// nodes at each horizontal distancevoiddfs(Node*root,inthd,intdepth,unordered_map<int,pair<int,int>>&hdMap){if(root==NULL)return;minHD=min(minHD,hd);maxHD=max(maxHD,hd);// If this horizontal distance is // being visited for the first time or// we're at a deeper level, update itif(hdMap.find(hd)==hdMap.end()||depth>=hdMap[hd].second){hdMap[hd]={root->data,depth};}dfs(root->left,hd-1,depth+1,hdMap);dfs(root->right,hd+1,depth+1,hdMap);}// Returns the bottom view of a binary treevector<int>bottomView(Node*root){if(root==NULL)return{};minHD=0,maxHD=0;// Map to store the last node's data and its depth// at each horizontal distanceunordered_map<int,pair<int,int>>hdMap;dfs(root,0,0,hdMap);vector<int>result;// Iterate through horizontal distances// in range from min HD to max HDfor(inthd=minHD;hd<=maxHD;hd++){result.push_back(hdMap[hd].first);}returnresult;}intmain(){// Create binary tree// 20// / \ // 8 22// / \ \ // 5 3 25// / \ /// 10 14 28Node*root=newNode(20);root->left=newNode(8);root->right=newNode(22);root->left->left=newNode(5);root->left->right=newNode(3);root->right->left=newNode(4);root->left->right->left=newNode(10);root->left->right->right=newNode(14);root->right->right=newNode(25);root->right->right->left=newNode(28);minHD=0;maxHD=0;vector<int>result=bottomView(root);for(intval:result){cout<<val<<" ";}}
Java
importjava.util.List;importjava.util.ArrayList;importjava.util.Map;importjava.util.HashMap;// Node StructureclassNode{intdata;Nodeleft,right;Node(intx){data=x;left=right=null;}}classGFG{staticintminHD,maxHD;// DFS function to fill hdMap with bottom-most nodes at each horizontal distancestaticvoiddfs(Noderoot,inthd,intdepth,Map<Integer,Pair>hdMap){if(root==null)return;minHD=Math.min(minHD,hd);maxHD=Math.max(maxHD,hd);// If this horizontal distance is // being visited for the first time or// we're at a deeper level, update itif(!hdMap.containsKey(hd)||depth>=hdMap.get(hd).depth){hdMap.put(hd,newPair(root.data,depth));}dfs(root.left,hd-1,depth+1,hdMap);dfs(root.right,hd+1,depth+1,hdMap);}// Returns the bottom view of a binary treestaticArrayList<Integer>bottomView(Noderoot){if(root==null)returnnewArrayList<>();minHD=0;maxHD=0;// Map to store the last node's data and its depth// at each horizontal distance (HD)Map<Integer,Pair>hdMap=newHashMap<>();dfs(root,0,0,hdMap);ArrayList<Integer>result=newArrayList<>();// Iterate through horizontal distances// in range from min HD to max HDfor(inthd=minHD;hd<=maxHD;hd++){result.add(hdMap.get(hd).data);}returnresult;}// Pair class to store // node data and its depthstaticclassPair{intdata,depth;Pair(intdata,intdepth){this.data=data;this.depth=depth;}}publicstaticvoidmain(String[]args){// Create binary tree// 20// / \// 8 22// / \ \// 5 3 25// / \ /// 10 14 28Noderoot=newNode(20);root.left=newNode(8);root.right=newNode(22);root.left.left=newNode(5);root.left.right=newNode(3);root.right.left=newNode(4);root.left.right.left=newNode(10);root.left.right.right=newNode(14);root.right.right=newNode(25);root.right.right.left=newNode(28);minHD=0;maxHD=0;ArrayList<Integer>result=bottomView(root);for(intval:result){System.out.print(val+" ");}}}
Python
# Node StructureclassNode:def__init__(self,x):self.data=xself.left=Noneself.right=None# Pair class to store # node data and its depthclassPair:def__init__(self,data,depth):self.data=dataself.depth=depthminHD=0maxHD=0# DFS function to fill hdMap with bottom-most nodes# at each horizontal distancedefdfs(root,hd,depth,hdMap):globalminHD,maxHDifrootisNone:returnminHD=min(minHD,hd)maxHD=max(maxHD,hd)# If this horizontal distance is # being visited for the first time or# we're at a deeper level, update itifhdnotinhdMapordepth>=hdMap[hd].depth:hdMap[hd]=Pair(root.data,depth)dfs(root.left,hd-1,depth+1,hdMap)dfs(root.right,hd+1,depth+1,hdMap)# Returns the bottom view of a binary treedefbottomView(root):ifrootisNone:return[]globalminHD,maxHDminHD=0maxHD=0# Map to store the last node's data and its depth# at each horizontal distance (HD)hdMap={}dfs(root,0,0,hdMap)result=[]# Iterate through horizontal distances# in range from min HD to max HDforhdinrange(minHD,maxHD+1):result.append(hdMap[hd].data)returnresultif__name__=="__main__":# Create binary tree# 20# / \# 8 22# / \ \# 5 3 25# / \ /# 10 14 28root=Node(20)root.left=Node(8)root.right=Node(22)root.left.left=Node(5)root.left.right=Node(3)root.right.left=Node(4)root.left.right.left=Node(10)root.left.right.right=Node(14)root.right.right=Node(25)root.right.right.left=Node(28)minHD=0maxHD=0result=bottomView(root)print(*result)
C#
usingSystem;usingSystem.Collections.Generic;// Node StructureclassNode{publicintdata;publicNodeleft,right;publicNode(intx){data=x;left=right=null;}}classGFG{staticintminHD,maxHD;// DFS function to fill hdMap with bottom-most // nodes at each horizontal distancestaticvoiddfs(Noderoot,inthd,intdepth,Dictionary<int,Pair>hdMap){if(root==null)return;minHD=Math.Min(minHD,hd);maxHD=Math.Max(maxHD,hd);// If this horizontal distance is // being visited for the first time or// we're at a deeper level, update itif(!hdMap.ContainsKey(hd)||depth>=hdMap[hd].depth){hdMap[hd]=newPair(root.data,depth);}dfs(root.left,hd-1,depth+1,hdMap);dfs(root.right,hd+1,depth+1,hdMap);}// Returns the bottom view of a binary treestaticList<int>bottomView(Noderoot){if(root==null)returnnewList<int>();minHD=0;maxHD=0;// Map to store the last node's data and its depth// at each horizontal distance (HD)Dictionary<int,Pair>hdMap=newDictionary<int,Pair>();dfs(root,0,0,hdMap);List<int>result=newList<int>();// Iterate through horizontal distances// in range from min HD to max HDfor(inthd=minHD;hd<=maxHD;hd++){result.Add(hdMap[hd].data);}returnresult;}// Pair class to store // node data and its depthclassPair{publicintdata,depth;publicPair(intdata,intdepth){this.data=data;this.depth=depth;}}publicstaticvoidMain(string[]args){// Create binary tree// 20// / \// 8 22// / \ \// 5 3 25// / \ /// 10 14 28Noderoot=newNode(20);root.left=newNode(8);root.right=newNode(22);root.left.left=newNode(5);root.left.right=newNode(3);root.right.left=newNode(4);root.left.right.left=newNode(10);root.left.right.right=newNode(14);root.right.right=newNode(25);root.right.right.left=newNode(28);minHD=0;maxHD=0;List<int>result=bottomView(root);foreach(intvalinresult){Console.Write(val+" ");}}}
JavaScript
// Node StructureclassNode{constructor(x){this.data=x;this.left=null;this.right=null;}}// Pair class to store // node data and its depthclassPair{constructor(data,depth){this.data=data;this.depth=depth;}}letminHD=0;letmaxHD=0;// DFS function to fill hdMap with bottom-most// nodes at each horizontal distancefunctiondfs(root,hd,depth,hdMap){if(root===null)return;minHD=Math.min(minHD,hd);maxHD=Math.max(maxHD,hd);// If this horizontal distance is new// or we're at a deeper level, update itif(!hdMap.has(hd)||depth>=hdMap.get(hd).depth){hdMap.set(hd,newPair(root.data,depth));}dfs(root.left,hd-1,depth+1,hdMap);dfs(root.right,hd+1,depth+1,hdMap);}// Returns the bottom view of a binary treefunctionbottomView(root){if(root===null)return[];minHD=0;maxHD=0;// Map to store the last node's data and its depth// at each horizontal distancelethdMap=newMap();dfs(root,0,0,hdMap);letresult=[];// Iterate through horizontal distances// in range from minHD to maxHDfor(lethd=minHD;hd<=maxHD;hd++){result.push(hdMap.get(hd).data);}returnresult;}// Driver code// Create binary tree// 20// / \// 8 22// / \ \// 5 3 25// / \ /// 10 14 28letroot=newNode(20);root.left=newNode(8);root.right=newNode(22);root.left.left=newNode(5);root.left.right=newNode(3);root.right.left=newNode(4);root.left.right.left=newNode(10);root.left.right.right=newNode(14);root.right.right=newNode(25);root.right.right.left=newNode(28);letresult=bottomView(root);console.log(...result);
Output
5 10 4 28 25
[Expected Approach - 2] Using BFS - O(n) Time and O(n) Space
The idea is to do BFS while maintaining a map for horizontal distance (key) and the last node (value). The value for a certain distance is updated as we progress in the level order traversal.
C++
#include<iostream>#include<vector>#include<unordered_map>#include<queue>usingnamespacestd;// Node StructureclassNode{public:intdata;Node*left;Node*right;Node(intx){data=x;left=right=nullptr;}};vector<int>bottomView(Node*root){if(!root)return{};// Map to store the last node's data// at each horizontal distanceunordered_map<int,int>hash;intminHD=0,maxHD=0;// Queue for level order traversal// storing <node, horizontal distance>queue<pair<Node*,int>>q;q.push({root,0});while(!q.empty()){autofront=q.front();q.pop();Node*node=front.first;inthd=front.second;// Update the horizontal distance -> node datahash[hd]=node->data;minHD=min(minHD,hd);maxHD=max(maxHD,hd);if(node->left)q.push({node->left,hd-1});if(node->right)q.push({node->right,hd+1});}vector<int>ans;for(inti=minHD;i<=maxHD;i++)ans.push_back(hash[i]);returnans;}intmain(){// Create binary tree// 20// / \ // 8 22// / \ \ // 5 3 25// / \ /// 10 14 28Node*root=newNode(20);root->left=newNode(8);root->right=newNode(22);root->left->left=newNode(5);root->left->right=newNode(3);root->right->left=newNode(4);root->left->right->left=newNode(10);root->left->right->right=newNode(14);root->right->right=newNode(25);root->right->right->left=newNode(28);vector<int>result=bottomView(root);for(intval:result){cout<<val<<" ";}}
Java
importjava.util.List;importjava.util.ArrayList;importjava.util.Map;importjava.util.HashMap;importjava.util.Queue;importjava.util.LinkedList;importjava.util.Arrays;// Node StructureclassNode{intdata;Nodeleft,right;Node(intx){data=x;left=right=null;}}classGFG{staticArrayList<Integer>bottomView(Noderoot){if(root==null)returnnewArrayList<>();// HashMap to store// <vertical_index, node data>HashMap<Integer,Integer>hash=newHashMap<>();intminHD=0;intmaxHD=0;// Queue for level order traversal // with pair<Node, vertical index>Queue<List<Object>>q=newLinkedList<>();q.offer(Arrays.asList(root,0));while(!q.isEmpty()){List<Object>top=q.poll();Nodenode=(Node)top.get(0);inthd=(Integer)top.get(1);// Update the horizontal distance -> node datahash.put(hd,node.data);minHD=Math.min(minHD,hd);maxHD=Math.max(maxHD,hd);if(node.left!=null){q.offer(Arrays.asList(node.left,hd-1));}if(node.right!=null){q.offer(Arrays.asList(node.right,hd+1));}}ArrayList<Integer>ans=newArrayList<>();for(inti=minHD;i<=maxHD;i++){ans.add(hash.get(i));}returnans;}publicstaticvoidmain(String[]args){// Create binary tree// 20// / \// 8 22// / \ \// 5 3 25// / \ /// 10 14 28Noderoot=newNode(20);root.left=newNode(8);root.right=newNode(22);root.left.left=newNode(5);root.left.right=newNode(3);root.right.left=newNode(4);root.left.right.left=newNode(10);root.left.right.right=newNode(14);root.right.right=newNode(25);root.right.right.left=newNode(28);ArrayList<Integer>result=bottomView(root);for(intval:result){System.out.print(val+" ");}}}
Python
fromcollectionsimportdeque# Node StructureclassNode:def__init__(self,x):self.data=xself.left=Noneself.right=NonedefbottomView(root):ifrootisNone:return[]# HashMap to store# <vertical_index, node data>hash={}minHD=0maxHD=0# Queue for level order traversal # with pair<Node, vertical index>q=deque()q.append([root,0])whileq:top=q.popleft()node=top[0]hd=top[1]# Update the horizontal distance -> node datahash[hd]=node.dataminHD=min(minHD,hd)maxHD=max(maxHD,hd)ifnode.leftisnotNone:q.append([node.left,hd-1])ifnode.rightisnotNone:q.append([node.right,hd+1])ans=[]foriinrange(minHD,maxHD+1):ans.append(hash[i])returnansif__name__=="__main__":# Create binary tree# 20# / \# 8 22# / \ \# 5 3 25# / \ /# 10 14 28root=Node(20)root.left=Node(8)root.right=Node(22)root.left.left=Node(5)root.left.right=Node(3)root.right.left=Node(4);root.left.right.left=Node(10)root.left.right.right=Node(14)root.right.right=Node(25)root.right.right.left=Node(28);result=bottomView(root)print(*result)
C#
usingSystem;usingSystem.Collections.Generic;// Node StructureclassNode{publicintdata;publicNodeleft,right;publicNode(intx){data=x;left=right=null;}}classGFG{staticList<int>bottomView(Noderoot){if(root==null)returnnewList<int>();// HashMap to store// <vertical_index, node data>Dictionary<int,int>hash=newDictionary<int,int>();intminHD=0;intmaxHD=0;// Queue for level order traversal// with pair<Node, vertical index>Queue<List<object>>q=newQueue<List<object>>();q.Enqueue(newList<object>{root,0});while(q.Count>0){List<object>top=q.Dequeue();Nodenode=(Node)top[0];inthd=(int)top[1];// Update the horizontal distance -> node datahash[hd]=node.data;minHD=Math.Min(minHD,hd);maxHD=Math.Max(maxHD,hd);if(node.left!=null){q.Enqueue(newList<object>{node.left,hd-1});}if(node.right!=null){q.Enqueue(newList<object>{node.right,hd+1});}}List<int>ans=newList<int>();for(inti=minHD;i<=maxHD;i++){ans.Add(hash[i]);}returnans;}staticvoidMain(string[]args){// Create binary tree// 20// / \// 8 22// / \ \// 5 3 25// / \ /// 10 14 28Noderoot=newNode(20);root.left=newNode(8);root.right=newNode(22);root.left.left=newNode(5);root.left.right=newNode(3);root.right.left=newNode(4);root.left.right.left=newNode(10);root.left.right.right=newNode(14);root.right.right=newNode(25);root.right.right.left=newNode(28);List<int>result=bottomView(root);foreach(intvalinresult){Console.Write(val+" ");}}}
JavaScript
// Node StructureclassNode{constructor(x){this.data=x;this.left=null;this.right=null;}}functionbottomView(root){if(root===null)return[];// HashMap to store// <vertical_index, node data>lethash=newMap();letminHD=0;letmaxHD=0;// Queue for level order traversal // with pair<Node, vertical index>letq=[];q.push([root,0]);while(q.length>0){lettop=q.shift();letnode=top[0];lethd=top[1];// Update the horizontal distance -> node datahash.set(hd,node.data);minHD=Math.min(minHD,hd);maxHD=Math.max(maxHD,hd);if(node.left!==null){q.push([node.left,hd-1]);}if(node.right!==null){q.push([node.right,hd+1]);}}letans=[];for(leti=minHD;i<=maxHD;i++){ans.push(hash.get(i));}returnans;}// Driver code// Create binary tree// 20// / \// 8 22// / \ \// 5 3 25// / \ /// 10 14 28letroot=newNode(20);root.left=newNode(8);root.right=newNode(22);root.left.left=newNode(5);root.left.right=newNode(3);root.right.left=newNode(4);root.left.right.left=newNode(10);root.left.right.right=newNode(14);root.right.right=newNode(25);root.right.right.left=newNode(28);letresult=bottomView(root);console.log(...result);