Vertical Traversal of a Binary Tree

Last Updated : 16 Oct, 2026

Given a binary Tree, find its vertical traversal starting from the leftmost level to the rightmost level.

Note: If multiple nodes are at the same horizontal distance from the root and on the same level, they should be printed in the order they appear in a level-order traversal (top-to-bottom, left-to-right).

Here, Horizontal distance is calculated from the root to a specific node by counting how many times we move left or right along the unique path from the root to that node.

Horizontal Distance = Number of right moves − Number of left moves in the path from the root to that node.

Examples:  

Input: root = [1, 2, 3, 4, 5, 6, 7, N, N, N, 8, N, 9, N, 10, 11, N]

1

Output: [[4], [2], [1, 5, 6, 11], [3, 8, 9], [7], [10]]
Explanation: The below image shows the horizontal distances used to print vertical traversal starting from the leftmost level to the rightmost level.

2

Input: root = [1, 2, 3, 4, 5, N, 6]

3

Output: [[4], [2], [1, 5], [3], [6]]
Explanation: From left to right the vertical order will be [[4], [2], [1, 5], [3], [6]]

Try It Yourself
redirect icon

[Naive Approach] Traversing the Tree for Each Vertical Line - O(n ^ 2) Time and O(n) Space

The idea is to first traverse the tree to find the minimum and maximum horizontal distances (HD) from the root. In the example tree, the minimum HD is -2 (node 4) and the maximum HD is 3 (node 10).

Working of Approach:

  • Find the minimum and maximum horizontal distances (HD) from the root.
  • Iterate through each vertical line from the minimum HD to the maximum HD.
  • Perform a level-order traversal (BFS) and collect nodes whose HD matches the current vertical line.
  • Store the collected nodes in the result in left-to-right vertical order.
C++
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;

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

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

// Finds the minimum and maximum horizontal distance in the tree
void findMinMax(Node *node, int &min, int &max, int hd)
{

    if (node == nullptr)
        return;

    if (hd < min)
        min = hd;
    else if (hd > max)
        max = hd;

    // Recur for left and right subtrees
    findMinMax(node->left, min, max, hd - 1);
    findMinMax(node->right, min, max, hd + 1);
}

// Collects all nodes at a given vertical distance in level-order
void collectVerticalLine(Node *root, int dist, vector<int> &line)
{

    int hd = 0;

    // Create a queue for level order traversal
    queue<pair<Node *, int>> q;
    q.push({root, 0});

    int mn = 0, mx = 0;
    while (!q.empty())
    {
        pair<Node *, int> curr = q.front();
        q.pop();

        Node *node = curr.first;
        hd = curr.second;
        if (hd == dist)
            line.push_back(node->data);

        if (node->left)
            q.push({node->left, hd - 1});
        if (node->right)
            q.push({node->right, hd + 1});
    }
}

// Returns the vertical order traversal of the tree
vector<vector<int>> verticalOrder(Node *root)
{
    vector<vector<int>> res;

    int min = 0, max = 0;
    findMinMax(root, min, max, 0);

    for (int line = min; line <= max; line++)
    {
        vector<int> verticalNodes;

        // storing nodes for each vertical lines
        collectVerticalLine(root, line, verticalNodes);

        res.push_back(verticalNodes);
    }

    return res;
}

int main()
{

    // Create binary tree
    //            1
    //          /   \
    //         2     3
    //        / \   / \
    //       4   5 6   7
    //            \  \   \
    //             8  9   10
    //            /
    //           11

    Node *root = new Node(1);
    root->left = new Node(2);
    root->right = new Node(3);
    root->left->left = new Node(4);
    root->left->right = new Node(5);
    root->right->left = new Node(6);
    root->right->right = new Node(7);
    root->left->right->right = new Node(8);
    root->right->left->right = new Node(9);
    root->right->right->right = new Node(10);
    root->left->right->right->left = new Node(11);

    vector<vector<int>> res = verticalOrder(root);

    cout << "[";
    for (int i = 0; i < res.size(); i++)
    {
        cout << "[";
        vector<int> line = res[i];
        for (int j = 0; j < line.size(); j++)
        {
            cout << line[j];
            if (j != line.size() - 1)
                cout << ", ";
        }
        cout << "]";
        if (i != res.size() - 1)
            cout << ", ";
    }

    cout << "]";
    cout << endl;

    return 0;
}
Java
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

// Node Structure
class Node {
    int data;
    Node left, right;

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

class GFG {

    // Finds the minimum and maximum horizontal distance in
    // the tree
    static void findMinMax(Node node, int[] min, int[] max,
                           int hd)
    {
        if (node == null)
            return;

        if (hd < min[0])
            min[0] = hd;
        else if (hd > max[0])
            max[0] = hd;

        // Recur for left and right subtrees
        findMinMax(node.left, min, max, hd - 1);
        findMinMax(node.right, min, max, hd + 1);
    }

    // Collects all nodes at a given vertical distance in
    // level-order
    static void collectVerticalLine(Node root, int dist,
                                    ArrayList<Integer> line)
    {
        int hd = 0;

        // Queue for level-order traversal
        Queue<ArrayList<Object> > q = new LinkedList<>();
        ArrayList<Object> first = new ArrayList<>();
        first.add(root);
        first.add(hd);
        q.add(first);

        while (!q.isEmpty()) {
            ArrayList<Object> curr = q.poll();
            Node node = (Node)curr.get(0);
            hd = (int)curr.get(1);

            if (hd == dist)
                line.add(node.data);

            if (node.left != null) {
                ArrayList<Object> leftNode
                    = new ArrayList<>();
                leftNode.add(node.left);
                leftNode.add(hd - 1);
                q.add(leftNode);
            }
            if (node.right != null) {
                ArrayList<Object> rightNode
                    = new ArrayList<>();
                rightNode.add(node.right);
                rightNode.add(hd + 1);
                q.add(rightNode);
            }
        }
    }

    // Returns the vertical order traversal of the tree
    static ArrayList<ArrayList<Integer> >
    verticalOrder(Node root)
    {
        ArrayList<ArrayList<Integer> > res
            = new ArrayList<>();

        int[] min = { 0 }, max = { 0 };
        findMinMax(root, min, max, 0);

        for (int line = min[0]; line <= max[0]; line++) {
            ArrayList<Integer> verticalNodes
                = new ArrayList<>();
            collectVerticalLine(root, line, verticalNodes);
            res.add(verticalNodes);
        }
        return res;
    }

    public static void main(String[] args)
    {

        // Create binary tree
        //            1
        //          /   \
        //         2     3
        //        / \   / \
        //       4   5 6   7
        //            \  \   \
        //             8  9   10
        //            /
        //           11

        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);
        root.right.left = new Node(6);
        root.right.right = new Node(7);
        root.left.right.right = new Node(8);
        root.right.left.right = new Node(9);
        root.right.right.right = new Node(10);
        root.left.right.right.left = new Node(11);

        ArrayList<ArrayList<Integer> > res
            = verticalOrder(root);

        System.out.print("[");
        for (int i = 0; i < res.size(); i++) {
            System.out.print("[");
            ArrayList<Integer> line = res.get(i);
            for (int j = 0; j < line.size(); j++) {
                System.out.print(line.get(j));
                if (j != line.size() - 1)
                    System.out.print(", ");
            }
            System.out.print("]");
            if (i != res.size() - 1)
                System.out.print(", ");
        }
        System.out.println("]");
    }
}
Python
from collections import deque

# Node Structure
class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None

# Returns the vertical order traversal of the tree
def findMinMax(node, minmax, hd):
    if node is None:
        return

    if hd < minmax["min"]:
        minmax["min"] = hd
    elif hd > minmax["max"]:
        minmax["max"] = hd


    # Recur for left and right subtrees
    findMinMax(node.left, minmax, hd - 1)
    findMinMax(node.right, minmax, hd + 1)

# Collects all nodes at a given vertical distance in level-order
def collectVerticalLine(root, dist, line):
    hd = 0

    # Create a queue for level order traversal
    q = deque()
    q.append((root, 0))

    while q:
        node, hd = q.popleft()
        if hd == dist:
            line.append(node.data)

        if node.left:
            q.append((node.left, hd - 1))
        if node.right:
            q.append((node.right, hd + 1))

# Finds the minimum and maximum horizontal distance in the tree
def verticalOrder(root):
    res = []

    minmax = {"min": 0, "max": 0}
    findMinMax(root, minmax, 0)

    for line in range(minmax["min"], minmax["max"] + 1):
        verticalNodes = []
        collectVerticalLine(root, line, verticalNodes)
        res.append(verticalNodes)

    return res

if __name__ == "__main__":
    
    #  Create binary tree
    #             1
    #           /   \
    #          2     3
    #         / \   / \
    #       4   5 6   7
    #             \  \   \
    #              8  9   10
    #             /
    #           11
    
    root = Node(1)
    root.left = Node(2)
    root.right = Node(3)
    root.left.left = Node(4)
    root.left.right = Node(5)
    root.right.left = Node(6)
    root.right.right = Node(7)
    root.left.right.right = Node(8)
    root.right.left.right = Node(9)
    root.right.right.right = Node(10)
    root.left.right.right.left = Node(11)

    res = verticalOrder(root)

    print("[", end="")
    for i in range(len(res)):
        print("[", end="")
        line = res[i]
        for j in range(len(line)):
            print(line[j], end="")
            if j != len(line) - 1:
                print(", ", end="")
        print("]", end="")
        if i != len(res) - 1:
            print(", ", end="")
    print("]")
C#
using System;
using System.Collections.Generic;

// Node Structure
class Node {
    public int data;
    public Node left, right;

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

class GFG {

    // Finds the minimum and maximum horizontal distance in
    // the tree
    static void findMinMax(Node node, ref int min,
                           ref int max, int hd)
    {
        if (node == null)
            return;

        if (hd < min)
            min = hd;
        else if (hd > max)
            max = hd;

        // Recur for left and right subtrees
        findMinMax(node.left, ref min, ref max, hd - 1);
        findMinMax(node.right, ref min, ref max, hd + 1);
    }

    // Collects all nodes at a given vertical distance in
    // level-order
    static void collectVerticalLine(Node root, int dist,
                                    List<int> line)
    {
        int hd = 0;

        // Create a queue for level order traversal
        Queue<(Node, int)> q = new Queue<(Node, int)>();
        q.Enqueue((root, 0));

        while (q.Count > 0) {
            var curr = q.Dequeue();
            Node node = curr.Item1;
            hd = curr.Item2;

            if (hd == dist)
                line.Add(node.data);

            if (node.left != null)
                q.Enqueue((node.left, hd - 1));
            if (node.right != null)
                q.Enqueue((node.right, hd + 1));
        }
    }

    // Returns the vertical order traversal of the tree
    static List<List<int> > verticalOrder(Node root)
    {
        List<List<int> > res = new List<List<int> >();

        int min = 0, max = 0;
        findMinMax(root, ref min, ref max, 0);

        for (int line = min; line <= max; line++) {
            List<int> verticalNodes = new List<int>();
            collectVerticalLine(root, line, verticalNodes);
            res.Add(verticalNodes);
        }

        return res;
    }

    static void Main()
    {

        // Create binary tree
        //            1
        //          /   \
        //         2     3
        //        / \   / \
        //       4   5 6   7
        //            \  \   \
        //             8  9   10
        //            /
        //           11

        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);
        root.right.left = new Node(6);
        root.right.right = new Node(7);
        root.left.right.right = new Node(8);
        root.right.left.right = new Node(9);
        root.right.right.right = new Node(10);
        root.left.right.right.left = new Node(11);

        List<List<int> > res = verticalOrder(root);

        Console.Write("[");
        for (int i = 0; i < res.Count; i++) {
            Console.Write("[");
            List<int> line = res[i];
            for (int j = 0; j < line.Count; j++) {
                Console.Write(line[j]);
                if (j != line.Count - 1)
                    Console.Write(", ");
            }
            Console.Write("]");
            if (i != res.Count - 1)
                Console.Write(", ");
        }
        Console.WriteLine("]");
    }
}
JavaScript
// Node Structure
class Node {
    constructor(x)
    {
        this.data = x;
        this.left = null;
        this.right = null;
    }
}

// Finds the minimum and maximum horizontal distance in the
// tree
function findMinMax(node, minmax, hd)
{
    if (!node)
        return;

    if (hd < minmax.min)
        minmax.min = hd;
    else if (hd > minmax.max)
        minmax.max = hd;

    // Recur for left and right subtrees
    findMinMax(node.left, minmax, hd - 1);
    findMinMax(node.right, minmax, hd + 1);
}

// Collects all nodes at a given vertical distance in
// level-order
function collectVerticalLine(root, dist, line)
{
    let hd = 0;

    // Create a queue for level order traversal
    let q = [];
    q.push([ root, 0 ]);

    while (q.length > 0) {
        let [node, currHd] = q.shift();
        hd = currHd;

        if (hd === dist)
            line.push(node.data);

        if (node.left)
            q.push([ node.left, hd - 1 ]);
        if (node.right)
            q.push([ node.right, hd + 1 ]);
    }
}

// Returns the vertical order traversal of the tree
function verticalOrder(root)
{
    let res = [];

    let minmax = {min : 0, max : 0};
    findMinMax(root, minmax, 0);

    for (let line = minmax.min; line <= minmax.max;
         line++) {
        let verticalNodes = [];
        collectVerticalLine(root, line, verticalNodes);
        res.push(verticalNodes);
    }

    return res;
}

// Driver Code

// Create binary tree
//            1
//          /   \
//         2     3
//        / \   / \
//       4   5 6   7
//            \  \   \
//             8  9   10
//            /
//           11

let root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
root.right.left = new Node(6);
root.right.right = new Node(7);
root.left.right.right = new Node(8);
root.right.left.right = new Node(9);
root.right.right.right = new Node(10);
root.left.right.right.left = new Node(11);

let res = verticalOrder(root);

process.stdout.write("[");
for (let i = 0; i < res.length; i++) {
    process.stdout.write("[");
    let line = res[i];
    for (let j = 0; j < line.length; j++) {
        process.stdout.write(line[j].toString());
        if (j !== line.length - 1)
            process.stdout.write(", ");
    }
    process.stdout.write("]");
    if (i !== res.length - 1)
        process.stdout.write(", ");
}
console.log("]");

Output
[[4], [2], [1, 5, 6, 11], [3, 8, 9], [7], [10]]

[Better Approach] DFS and Sorting – O(n log n) Time and O(n) Space

The idea is to traverse the tree using Depth-First Search (DFS) and store each node's value and level according to its horizontal distance (HD) from the root.

  • This groups the nodes belonging to the same vertical line.
  • Since DFS may visit deeper nodes before shallower nodes, we sort the nodes in each vertical line by their levels to maintain the correct order.
  • Finally, we collect the node values from left to right to obtain the vertical order traversal.

Working of Approach:

  • Traverse the tree using DFS and track the horizontal distance and level of each node.
  • Sort the nodes in each vertical line by level using a stable sort, preserving left-to-right order when levels are equal.
  • Collect the node values from left to right to obtain the result.
C++
#include <algorithm>
#include <iostream>
#include <map>
#include <queue>
#include <vector>
using namespace std;

class Node
{
  public:
    int data;
    Node *left;
    Node *right;
    Node(int x)
    {
        data = x;
        left = right = nullptr;
    }
};

// Performs DFS to map each node to its horizontal distance and level
void dfs(Node *root, int hd, int lvl, map<int, vector<pair<int, int>>> &verticalLines)
{
    if (root == nullptr)
        return;

    // storing node value and level
    verticalLines[hd].push_back({root->data, lvl});

    // Recur for left and right subtrees
    dfs(root->left, hd - 1, lvl + 1, verticalLines);
    dfs(root->right, hd + 1, lvl + 1, verticalLines);
}

// Collects all vertical lines after DFS traversal and sorting by level
vector<vector<int>> verticalOrder(Node *root)
{
    map<int, vector<pair<int, int>>> verticalLines;

    dfs(root, 0, 0, verticalLines);
    vector<vector<int>> res;

    for (auto &kv : verticalLines)
    {
        vector<pair<int, int>> lines = kv.second;

        // Sorting based on level
        stable_sort(lines.begin(), lines.end(), [](auto &a, auto &b) { return a.second < b.second; });

        vector<int> line;
        for (auto &node : lines)
        {
            line.push_back(node.first);
        }
        res.push_back(line);
    }

    return res;
}

int main()
{
    // Create binary tree
    //            1
    //          /   \
    //         2     3
    //        / \   / \
    //       4   5  6   7
    //            \  \   \
    //             8  9   10
    //            /
    //           11

    Node *root = new Node(1);
    root->left = new Node(2);
    root->right = new Node(3);
    root->left->left = new Node(4);
    root->left->right = new Node(5);
    root->right->left = new Node(6);
    root->right->right = new Node(7);
    root->left->right->right = new Node(8);
    root->right->left->right = new Node(9);
    root->right->right->right = new Node(10);
    root->left->right->right->left = new Node(11);

    vector<vector<int>> res = verticalOrder(root);

    cout << "[";
    for (int i = 0; i < res.size(); i++)
    {
        cout << "[";
        vector<int> line = res[i];
        for (int j = 0; j < line.size(); j++)
        {
            cout << line[j];
            if (j != line.size() - 1)
                cout << ", ";
        }
        cout << "]";
        if (i != res.size() - 1)
            cout << ", ";
    }
    cout << "]" << endl;
}
Java
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

// Node Structure
class Node {
    int data;
    Node left, right;

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

class GFG {

    // Performs DFS to map each node to its horizontal
    // distance and level
    static ArrayList<ArrayList<Integer> >
    verticalOrder(Node root)
    {
        TreeMap<Integer, ArrayList<ArrayList<Integer> > >
            map = new TreeMap<>();

        dfs(root, 0, 0, map);
        ArrayList<ArrayList<Integer> > res
            = new ArrayList<>();

        for (int hd : map.keySet()) {
            ArrayList<ArrayList<Integer> > lines
                = map.get(hd);

            // Sorting based on level (2nd element in list)
            Collections.sort(lines, Comparator.comparingInt(
                                        a -> a.get(1)));

            ArrayList<Integer> line = new ArrayList<>();
            for (ArrayList<Integer> node : lines) {

                // add only value, not level
                line.add(node.get(0));
            }
            res.add(line);
        }

        return res;
    }

    // Collects all vertical lines after DFS traversal and
    // sorting by level
    static void
    dfs(Node root, int hd, int lvl,
        TreeMap<Integer, ArrayList<ArrayList<Integer> > >
            verticalLines)
    {

        if (root == null)
            return;

        ArrayList<ArrayList<Integer> > line
            = verticalLines.getOrDefault(hd,
                                         new ArrayList<>());

        // store node value and level as a small list
        ArrayList<Integer> nodeInfo = new ArrayList<>();
        nodeInfo.add(root.data);
        nodeInfo.add(lvl);
        line.add(nodeInfo);

        verticalLines.put(hd, line);

        // Recur for left and right subtrees
        dfs(root.left, hd - 1, lvl + 1, verticalLines);
        dfs(root.right, hd + 1, lvl + 1, verticalLines);
    }

    public static void main(String[] args)
    {

        // Create binary tree
        //            1
        //          /   \
        //         2     3
        //        / \   / \
        //       4   5 6   7
        //            \  \   \
        //             8  9   10
        //            /
        //           11

        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);
        root.right.left = new Node(6);
        root.right.right = new Node(7);
        root.left.right.right = new Node(8);
        root.right.left.right = new Node(9);
        root.right.right.right = new Node(10);
        root.left.right.right.left = new Node(11);

        ArrayList<ArrayList<Integer> > res
            = verticalOrder(root);

        System.out.print("[");
        for (int i = 0; i < res.size(); i++) {
            System.out.print("[");
            List<Integer> line = res.get(i);
            for (int j = 0; j < line.size(); j++) {
                System.out.print(line.get(j));
                if (j != line.size() - 1)
                    System.out.print(", ");
            }
            System.out.print("]");
            if (i != res.size() - 1)
                System.out.print(", ");
        }
        System.out.println("]");
    }
}
Python
from collections import defaultdict

# Node Structure
class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None

# Collects all vertical lines after DFS traversal and sorting by level
def verticalOrder(root):
    verticalLines = defaultdict(list)

    dfs(root, 0, 0, verticalLines)
    res = []

    for hd in sorted(verticalLines.keys()):
        lines = verticalLines[hd]

        # Sorting based on level
        lines.sort(key=lambda x: x[1])

        line = []
        for node in lines:
            line.append(node[0])
        res.append(line)

    return res

# Performs DFS to map each node to its horizontal distance and level
def dfs(root, hd, lvl, verticalLines):
    if root is None:
        return

    # storing node value and level
    verticalLines[hd].append((root.data, lvl))

    # Recur for left and right subtrees
    dfs(root.left, hd - 1, lvl + 1, verticalLines)
    dfs(root.right, hd + 1, lvl + 1, verticalLines)


if __name__ == "__main__":
    # Create binary tree
    #         1
    #       /   \
    #      2     3
    #     / \   / \
    #   4   5 6   7
    #         \  \   \
    #          8  9   10
    #         /
    #       11

    root = Node(1)
    root.left = Node(2)
    root.right = Node(3)
    root.left.left = Node(4)
    root.left.right = Node(5)
    root.right.left = Node(6)
    root.right.right = Node(7)
    root.left.right.right = Node(8)
    root.right.left.right = Node(9)
    root.right.right.right = Node(10)
    root.left.right.right.left = Node(11)

    res = verticalOrder(root)

    print("[", end="")
    for i in range(len(res)):
        print("[", end="")
        line = res[i]
        for j in range(len(line)):
            print(line[j], end="")
            if j != len(line) - 1:
                print(", ", end="")
        print("]", end="")
        if i != len(res) - 1:
            print(", ", end="")
    print("]")
C#
using System;
using System.Collections.Generic;
using System.Linq;

// Node Structure
class Node {
    public int data;
    public Node left, right;

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

class GFG {

    // Collects all vertical lines after DFS traversal and
    // sorting by level
    static List<List<int>> verticalOrder(Node root)
    {
        SortedDictionary<int, List<int[]>> map
            = new SortedDictionary<int, List<int[]>>();

        dfs(root, 0, 0, map);
        List<List<int>> res = new List<List<int>>();

        foreach(int hd in map.Keys)
        {
            List<int[]> lines = map[hd];

            // Sorting based on level
            lines = lines.OrderBy(a => a[1]).ToList();

            List<int> line = new List<int>();
            foreach(int[] node in lines)
            {
                line.Add(node[0]);
            }
            res.Add(line);
        }

        return res;
    }

    // Performs DFS to map each node to its horizontal
    // distance and level
    static void
    dfs(Node root, int hd, int lvl,
        SortedDictionary<int, List<int[]>> verticalLines)
    {
        if (root == null)
            return;

        if (!verticalLines.ContainsKey(hd))
            verticalLines[hd] = new List<int[]>();

        // storing node value and level
        verticalLines[hd].Add(new int[] { root.data, lvl });

        // Recur for left and right subtrees
        dfs(root.left, hd - 1, lvl + 1, verticalLines);
        dfs(root.right, hd + 1, lvl + 1, verticalLines);
    }

    static void Main(string[] args)
    {
        // Create binary tree
        //            1
        //          /   \
        //         2     3
        //        / \   / \
        //       4   5 6   7
        //            \  \   \
        //             8  9   10
        //            /
        //           11
        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);
        root.right.left = new Node(6);
        root.right.right = new Node(7);
        root.left.right.right = new Node(8);
        root.right.left.right = new Node(9);
        root.right.right.right = new Node(10);
        root.left.right.right.left = new Node(11);

        List<List<int> > res = verticalOrder(root);

        Console.Write("[");
        for (int i = 0; i < res.Count; i++) {
            Console.Write("[");
            List<int> line = res[i];
            for (int j = 0; j < line.Count; j++) {
                Console.Write(line[j]);
                if (j != line.Count - 1)
                    Console.Write(", ");
            }
            Console.Write("]");
            if (i != res.Count - 1)
                Console.Write(", ");
        }
        Console.WriteLine("]");
    }
}
JavaScript
// Node Structure
class Node {
    constructor(x)
    {
        this.data = x;
        this.left = null;
        this.right = null;
    }
}

// Collects all vertical lines after DFS traversal and
// sorting by level
function verticalOrder(root)
{
    let map = new Map();

    dfs(root, 0, 0, map);
    let res = [];

    let keys = Array.from(map.keys()).sort((a, b) => a - b);
    for (let hd of keys) {
        let lines = map.get(hd);

        // Sorting based on level
        lines.sort((a, b) => a[1] - b[1]);

        let line = [];
        for (let node of lines) {
            line.push(node[0]);
        }
        res.push(line);
    }

    return res;
}

// Performs DFS to map each node to its horizontal distance
// and level
function dfs(root, hd, lvl, verticalLines)
{
    if (!root)
        return;

    let line = verticalLines.get(hd) || [];

    // storing node value and level
    line.push([ root.data, lvl ]);
    verticalLines.set(hd, line);

    // Recur for left and right subtrees
    dfs(root.left, hd - 1, lvl + 1, verticalLines);
    dfs(root.right, hd + 1, lvl + 1, verticalLines);
}

// Driver code

// Create binary tree
//            1
//          /   \
//         2     3
//        / \   / \
//       4   5 6   7
//            \  \   \
//             8  9   10
//            /
//           11
let root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
root.right.left = new Node(6);
root.right.right = new Node(7);
root.left.right.right = new Node(8);
root.right.left.right = new Node(9);
root.right.right.right = new Node(10);
root.left.right.right.left = new Node(11);

let res = verticalOrder(root);

process.stdout.write("[");
for (let i = 0; i < res.length; i++) {
    process.stdout.write("[");
    let line = res[i];
    for (let j = 0; j < line.length; j++) {
        process.stdout.write(line[j].toString());
        if (j != line.length - 1)
            process.stdout.write(", ");
    }
    process.stdout.write("]");
    if (i != res.length - 1)
        process.stdout.write(", ");
}
console.log("]");

Output
[[4], [2], [1, 5, 6, 11], [3, 8, 9], [7], [10]]

[Expected Approach] BFS – O(n) Time and O(n) Space

The idea is to traverse the tree using Breadth-First Search (BFS) and store each node's value in a map based on its horizontal distance (HD) from the root.

  • The horizontal distance decreases by 1 for the left child and increases by 1 for the right child.
  • Since BFS visits nodes level by level, the nodes are stored in the correct order within each vertical line without requiring additional sorting.
  • Finally, we collect the nodes from the minimum to the maximum horizontal distance to obtain the vertical order traversal.

Working of Approach:

  • Initialize a queue with the root node and its horizontal distance as 0.
  • Traverse the tree using BFS and store each node's value at its corresponding horizontal distance.
  • Update the minimum and maximum horizontal distances during traversal.
  • Collect the nodes from the minimum to the maximum horizontal distance to obtain the result.
C++
#include <algorithm>
#include <iostream>
#include <map>
#include <queue>
#include <unordered_map>
#include <vector>
using namespace std;

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

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

vector<vector<int>> verticalOrder(Node *root)
{

    // Queue to store nodes and their vertical levels.
    unordered_map<int, vector<int>> lst;

    // Queue to store nodes and their vertical levels.
    queue<pair<Node *, int>> q;
    q.push({root, 0});

    int mn = 0, mx = 0;

    while (!q.empty())
    {
        auto c = q.front();
        mn = min(mn, c.second);
        mx = max(mx, c.second);
        q.pop();

        // adding node to the corresponding vertical level.
        lst[c.second].push_back(c.first->data);

        // pushing left child with decreased vertical level.
        if (c.first->left)
            q.push({c.first->left, c.second - 1});

        // pushing right child with increased vertical level.
        if (c.first->right)
            q.push({c.first->right, c.second + 1});
    }

    // creating the result vector in vertical order.
    vector<vector<int>> res;
    for (int i = mn; i <= mx; i++)
        res.push_back(lst[i]);

    return res;
}

int main()
{
    // Create binary tree
    //            1
    //          /   \
    //         2     3
    //        / \   / \
    //       4   5 6   7
    //            \  \   \
    //             8  9   10
    //            /
    //           11

    Node *root = new Node(1);
    root->left = new Node(2);
    root->right = new Node(3);
    root->left->left = new Node(4);
    root->left->right = new Node(5);
    root->right->left = new Node(6);
    root->right->right = new Node(7);
    root->left->right->right = new Node(8);
    root->right->left->right = new Node(9);
    root->right->right->right = new Node(10);
    root->left->right->right->left = new Node(11);

    vector<vector<int>> res = verticalOrder(root);

    cout << "[";
    for (int i = 0; i < res.size(); i++)
    {
        cout << "[";
        vector<int> line = res[i];
        for (int j = 0; j < line.size(); j++)
        {
            cout << line[j];
            if (j != line.size() - 1)
                cout << ", ";
        }
        cout << "]";
        if (i != res.size() - 1)
            cout << ", ";
    }
    cout << "]" << endl;
}
Java
import java.util.*;

class Node {
    public int data;
    public Node left;
    public Node right;

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

public class GFG {

    public static ArrayList<ArrayList<Integer> >
    verticalOrder(Node root)
    {
        // Map to store nodes at each vertical level.
        Map<Integer, ArrayList<Integer> > lst
            = new HashMap<>();

        if (root == null)
            return new ArrayList<>();

        // Queue to store nodes and their vertical levels.
        Queue<AbstractMap.SimpleEntry<Node, Integer> > q
            = new LinkedList<>();
        q.add(new AbstractMap.SimpleEntry<>(root, 0));

        int mn = 0, mx = 0;

        while (!q.isEmpty()) {
            AbstractMap.SimpleEntry<Node, Integer> c
                = q.poll();

            Node node = c.getKey();
            int hd = c.getValue();

            mn = Math.min(mn, hd);
            mx = Math.max(mx, hd);

            // Adding node to the corresponding vertical
            // level.
            lst.computeIfAbsent(hd, k -> new ArrayList<>())
                .add(node.data);

            // Pushing left child with decreased vertical
            // level.
            if (node.left != null)
                q.add(new AbstractMap.SimpleEntry<>(
                    node.left, hd - 1));

            // Pushing right child with increased vertical
            // level.
            if (node.right != null)
                q.add(new AbstractMap.SimpleEntry<>(
                    node.right, hd + 1));
        }

        // Creating the result in vertical order.
        ArrayList<ArrayList<Integer> > res
            = new ArrayList<>();

        for (int i = mn; i <= mx; i++)
            res.add(lst.get(i));

        return res;
    }

    public static void main(String[] args)
    {
        // Create binary tree
        //            1
        //          /   \
        //         2     3
        //        / \   / \
        //       4   5 6   7
        //            \  \   \
        //             8  9   10
        //            /
        //           11

        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);
        root.right.left = new Node(6);
        root.right.right = new Node(7);
        root.left.right.right = new Node(8);
        root.right.left.right = new Node(9);
        root.right.right.right = new Node(10);
        root.left.right.right.left = new Node(11);

        ArrayList<ArrayList<Integer> > res
            = verticalOrder(root);

        System.out.print("[");
        for (int i = 0; i < res.size(); i++) {
            System.out.print("[");
            ArrayList<Integer> line = res.get(i);

            for (int j = 0; j < line.size(); j++) {
                System.out.print(line.get(j));
                if (j != line.size() - 1)
                    System.out.print(", ");
            }

            System.out.print("]");
            if (i != res.size() - 1)
                System.out.print(", ");
        }

        System.out.println("]");
    }
}
Python
from collections import deque, defaultdict

# Node Structure
class Node:
    def __init__(self, x):
        self.data = x
        self.left = None
        self.right = None

def verticalOrder(root):
    if root is None:
        return []

    # Map to store nodes and their vertical levels.
    lst = defaultdict(list)

    # Queue to store nodes and their vertical levels.
    q = deque([(root, 0)])

    mn = 0
    mx = 0

    while q:
        node, val = q.popleft()
        mn = min(mn, val)
        mx = max(mx, val)

        # adding node to the corresponding vertical level.
        lst[val].append(node.data)

        # pushing left child with decreased vertical level.
        if node.left:
            q.append((node.left, val - 1))

        # pushing right child with increased vertical level.
        if node.right:
            q.append((node.right, val + 1))

    # creating the result vector in vertical order.
    res = []
    for i in range(mn, mx + 1):
        res.append(lst[i])

    return res


if __name__ == "__main__":
    
    # Create binary tree
    #            1
    #          /   \
    #         2     3
    #        / \   / \
    #       4   5 6   7
    #            \  \   \
    #             8  9   10
    #            /
    #           11
    
    root = Node(1)
    root.left = Node(2)
    root.right = Node(3)
    root.left.left = Node(4)
    root.left.right = Node(5)
    root.right.left = Node(6)
    root.right.right = Node(7)
    root.left.right.right = Node(8)
    root.right.left.right = Node(9)
    root.right.right.right = Node(10)
    root.left.right.right.left = Node(11)

    res = verticalOrder(root)

    print("[", end="")
    for i in range(len(res)):
        print("[", end="")
        line = res[i]
        for j in range(len(line)):
            print(line[j], end="")
            if j != len(line) - 1:
                print(", ", end="")
        print("]", end="")
        if i != len(res) - 1:
            print(", ", end="")
    print("]")
C#
using System;
using System.Collections.Generic;
using System.Linq;

// Node Structure
class Node {
    public int data;
    public Node left, right;

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

class GFG {

    static List<List<int> > verticalOrder(Node root)
    {
        List<List<int> > res = new List<List<int> >();
        if (root == null)
            return res;

        // Map to store nodes and their vertical levels.
        Dictionary<int, List<int> > lst
            = new Dictionary<int, List<int> >();

        // Queue to store nodes and their vertical levels.
        Queue<(Node, int)> q = new Queue<(Node, int)>();
        q.Enqueue((root, 0));

        int mn = 0, mx = 0;

        while (q.Count > 0) {
            var curr = q.Dequeue();
            Node node = curr.Item1;
            int val = curr.Item2;

            mn = Math.Min(mn, val);
            mx = Math.Max(mx, val);

            // adding node to the corresponding vertical
            // level.
            if (!lst.ContainsKey(val))
                lst[val] = new List<int>();
            lst[val].Add(node.data);

            // pushing left child with decreased vertical
            // level.
            if (node.left != null)
                q.Enqueue((node.left, val - 1));

            // pushing right child with increased vertical
            // level.
            if (node.right != null)
                q.Enqueue((node.right, val + 1));
        }

        // creating the result vector in vertical order.
        for (int i = mn; i <= mx; i++)
            res.Add(lst[i]);

        return res;
    }

    static void Main(string[] args)
    {

        // Create binary tree
        //            1
        //          /   \
        //         2     3
        //        / \   / \
        //       4   5 6   7
        //            \  \   \
        //             8  9   10
        //            /
        //           11

        Node root = new Node(1);
        root.left = new Node(2);
        root.right = new Node(3);
        root.left.left = new Node(4);
        root.left.right = new Node(5);
        root.right.left = new Node(6);
        root.right.right = new Node(7);
        root.left.right.right = new Node(8);
        root.right.left.right = new Node(9);
        root.right.right.right = new Node(10);
        root.left.right.right.left = new Node(11);

        List<List<int> > res = verticalOrder(root);

        Console.Write("[");
        for (int i = 0; i < res.Count; i++) {
            Console.Write("[");
            List<int> line = res[i];
            for (int j = 0; j < line.Count; j++) {
                Console.Write(line[j]);
                if (j != line.Count - 1)
                    Console.Write(", ");
            }
            Console.Write("]");
            if (i != res.Count - 1)
                Console.Write(", ");
        }
        Console.WriteLine("]");
    }
}
JavaScript
// Node Structure
class Node {
    constructor(x)
    {
        this.data = x;
        this.left = null;
        this.right = null;
    }
}

// Custom Queue Implementation
class Queue {
    constructor()
    {
        this.items = [];
        this.frontIndex = 0;
    }

    enqueue(element) { this.items.push(element); }

    dequeue()
    {
        if (this.isEmpty())
            return null;
        const item = this.items[this.frontIndex];
        this.frontIndex++;
        // Optional: Reset array if frontIndex gets large
        if (this.frontIndex > 1000) {
            this.items = this.items.slice(this.frontIndex);
            this.frontIndex = 0;
        }
        return item;
    }

    isEmpty()
    {
        return this.frontIndex >= this.items.length;
    }

    size() { return this.items.length - this.frontIndex; }
}

function verticalOrder(root)
{
    if (!root)
        return [];

    // Map to store nodes and their vertical levels
    const lst = new Map();

    // Use our custom queue
    const q = new Queue();
    q.enqueue([ root, 0 ]);

    let mn = 0, mx = 0;

    while (!q.isEmpty()) {
        const [node, val] = q.dequeue();

        mn = Math.min(mn, val);
        mx = Math.max(mx, val);

        if (!lst.has(val))
            lst.set(val, []);
        lst.get(val).push(node.data);

        if (node.left)
            q.enqueue([ node.left, val - 1 ]);
        if (node.right)
            q.enqueue([ node.right, val + 1 ]);
    }

    // Build the result in vertical order
    const res = [];
    for (let i = mn; i <= mx; i++) {
        res.push(lst.get(i));
    }

    return res;
}

// Driver code
//            1
//          /   \
//         2     3
//        / \   / \
//       4   5 6   7
//            \  \   \
//             8  9   10
//            /
//           11
let root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
root.right.left = new Node(6);
root.right.right = new Node(7);
root.left.right.right = new Node(8);
root.right.left.right = new Node(9);
root.right.right.right = new Node(10);
root.left.right.right.left = new Node(11);

let res = verticalOrder(root);

// Display result
process.stdout.write("[");
for (let i = 0; i < res.length; i++) {
    process.stdout.write("[");
    let line = res[i];
    for (let j = 0; j < line.length; j++) {
        process.stdout.write(line[j].toString());
        if (j != line.length - 1)
            process.stdout.write(", ");
    }
    process.stdout.write("]");
    if (i != res.length - 1)
        process.stdout.write(", ");
}
console.log("]");

Output
[[4], [2], [1, 5, 6, 11], [3, 8, 9], [7], [10]]
Comment