Output: 4 2 12 3 7 Explanation: The below image shows the horizontal distances used to print vertical traversal starting from the leftmost level to the rightmost level.
[Naive Approach] Using map - O(n log n) Time and O(n) Space
We need to check the Horizontal Distances from the root for all nodes. If two nodes have the same Horizontal Distance (HD), then they are on the same vertical line. The idea of HD is simple. HD for root is 0, a right edge (edge connecting to right subtree) is considered as +1 horizontal distance and a left edge is considered as -1 horizontal distance. For example, in the above tree, HD for Node 4 is at -2, HD for Node 2 is -1, HD for 5 and 6 is 0 and HD for node 7 is +2.
For each node, decrement HD by 1 for the left subtree and increment HD by 1 for the right subtree.
For each HD, add the node's value to a map that tracks the sum of nodes at each horizontal distance.
Once traversal is complete, extract and return the sums from the map in sorted order of HDs.
Output
4 2 12 3 7
[Expected Approach] Using Hash map - O(n) Time and O(n) Space
The approach is same as above but here we are using hash map so time complexity will be reduces. Here we summing node values by their horizontal distance (hd) in a hash map, then return the vertical sums for each hd from minimum to maximum.
Algorithm:
Traverse the binary tree in-order, keeping track of the horizontal distance (hd) for each node.
For each node, add its value to a hashmap(mp) using the hd as the key.
Update the minimum and maximum hd values encountered during traversal.
After traversal, retrieve the sums from the map for all horizontal distances between the minimum and maximum hd values.
Return the list of vertical sums in order of their horizontal distances.
Output
4 2 12 3 7
[Alternate Approach] Using Doubly Linked List (Space Optimized) – O(n) Time and O(h) Space
The idea is to compute vertical sums without using a map or explicitly storing horizontal distances. A Doubly Linked List (DLL) is used where each node represents a vertical line of the binary tree.
While traversing the tree:
The value of each node is added to the current DLL node. Moving to the left child corresponds to moving to the previous (prev) DLL node and adding value to the linked list node. Moving to the right child corresponds to moving to the next (next) DLL node and adding value to the linked list node. If the required DLL node does not exist, a new node is created.
In this way, the DLL grows dynamically and maintains the order of vertical lines implicitly. After traversal, we move to the leftmost DLL node and traverse towards the right to collect all vertical sums in order.
Step 1: Create a DLL node head with value 0 for the root. Call: verticalSumUtil(1, head)
Step 2: Add root value (1). DLL: [1]
Step 3: Move to left child (2).
Create prev node and add 2.
DLL: [2] <-> [1]
Step 4: Move to left child (4).
Create another prev node and add 4.
DLL: [4] <-> [2] <-> [1]
Step 5: After node 4, recursion backtracks to node 2. Since left subtree is processed, move to right child (5). Node 5 lies in the same vertical line as root.
Add 5 → 1 + 5 = 6.
DLL: [4] <-> [2] <-> [6]
Step 6: Move to right child (3).
Create next node and add 3.
DLL: [4] <-> [2] <-> [6] <-> [3]
Step 7: Move to left child (6). It lies in the same vertical line as middle. Add 6 → 6 + 6 = 12. DLL: [4] <-> [2] <-> [12] <-> [3]
Step 8: Move to right child (7).
Create next node and add 7.
DLL: [4] <-> [2] <-> [12] <-> [3] <-> [7]
After traversal: Move to the leftmost DLL node and traverse towards right to collect all vertical sums.