0% completed
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]
- 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]
- 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]
- 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
-
Check if the root is null:
- If the root is null, return an empty list since there is no tree to process.
-
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.
- Create a
-
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.
- A reference to a
- 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))
).
- Create a
-
Perform BFS traversal:
- While the queue is not empty:
- Dequeue the front element:
- Remove the front element from the queue. This gives us a node and its horizontal distance.
- 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.
- 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
).
- 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.,
- 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
).
- 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.,
- Dequeue the front element:
- While the queue is not empty:
-
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.
-
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:
-
Initialize the queue and map:
- Queue:
[(10, 0)]
(Root node with HD = 0) - Map:
{}
(Empty at the start)
- Queue:
-
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)]
.
- Dequeue
-
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 of7
+ 1). - Queue:
[(4, 1), (9, 0)]
.
- Dequeue
-
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)]
.
- Dequeue
-
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)]
.
- Dequeue
-
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)]
.
- Dequeue
-
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.
- Dequeue
-
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]
.
- The map contains:
Code
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).
.....
.....
.....
Table of Contents
Contents are not accessible
Contents are not accessible
Contents are not accessible
Contents are not accessible
Contents are not accessible