Problem Statement

Given a Binary Tree, find the vertical traversal of it starting from the leftmost level to the rightmost level.
If there are multiple nodes passing through a vertical line, then they should be printed as they appear in level order traversal of the tree.

Pattern: Related: Top - Bottom View of a Tree


Solution

Approach.

  • Keep track of axis using wrapper class, and (node.left -> axis-1 , node.right -> axis + 1)
  • Level Order Traversal
  • Use a Ordered Hashmap in java TreeMap to store LinkedList Node values, mapped to their axes.
  • Conver to arraylist of lists and return 🤷
static class AxisNode {
	int axis;
	Node node;
	
	AxisNode(int axis, Node node) {
		this.axis = axis;
		this.node = node;
	}
}
 
public List<List<Integer>> verticalTraversal(Node root) {
	TreeMap<Integer, LinkedList<Integer>> axesMap = new TreeMap<>();
	Queue<AxisNode> q = new LinkedList<>();
	
	if (root == null) return new ArrayList<>();  // return empty list
	
	// levelorder traversal to create axesMap
	q.add(new AxisNode(0, root));
	while (!q.isEmpty()) {
		// get axis & node
		AxisNode an = q.remove();
		int axis = an.axis;
		Node node = an.node;
		
		if (!axesMap.containsKey(axis)) 
			axesMap.put(axis, new LinkedList<>());
		axesMap.get(an.axis).add(an.node.val);
		
		if (node.left != null) q.add(new AxisNode(axis - 1, node.left));
		if (node.right != null) q.add(new AxisNode(axis + 1, node.right));
	}
	
	return new ArrayList<>(axesMap.values());
}
  • Returns a List<List<Integer>> of the nodes of vertical columns from left to right

GFG Variation

For a single ArrayList like in the GFG Problem, use this code:

class AxisNode {
	int axis;
	Node node;
	AxisNode(int axis, Node node) {
		this.axis = axis;
		this.node = node;
	}
}
 
public ArrayList<Integer> verticalOrder (Node root){
	TreeMap<Integer, LinkedList<Integer>> axesMap= new TreeMap<>();
	Queue<AxisNode> q = new LinkedList<>();
	
	if(root == null) return new ArrayList<Integer>();  // return empty list
	
	// levelorder traversal to create axesMap
	q.add(new AxisNode(0, root));
	while(!q.isEmpty()) {
		
		// get axis & node
		AxisNode an = q.remove();
		int axis = an.axis;
		Node node = an.node;
		
		if(!axesMap.containsKey(axis))	
			axesMap.put(axis, new LinkedList<>());
		axesMap.get(an.axis).add(an.node.data);
		
		if(node.left != null) q.add(new AxisNode(axis - 1, node.left));
		if(node.right != null) q.add(new AxisNode(axis + 1, node.right));
	}
	
	ArrayList<Integer> vTrav = new ArrayList<>();
	for(LinkedList<Integer> list : axesMap.values())
		for(Integer val : list)
			vTrav.add(val);
	// return arraylist of sorted map
	return vTrav;
}

Leetcode Variation

For this stupidity 🙄 you need to change your code to sort level traversals too.😒

static class AxisNode {
	int axis;
	TreeNode node;
	AxisNode(int axis, TreeNode node) {
		this.axis = axis;
		this.node = node;
	}
}
 
public List<List<Integer>> verticalTraversal (TreeNode root){
	TreeMap<Integer, LinkedList<Integer>> axesMap= new TreeMap<>();
	Queue<AxisNode> q = new LinkedList<>();
 
	if(root == null) return new ArrayList<>();  // return empty list
	q.add(new AxisNode(0, root));
 
	// levelorder traversal to create axesMap
	while(!q.isEmpty()) {
		int size = q.size();
		ArrayList<AxisNode> levelList = new ArrayList<>();
		while(size-- > 0) {
			// get axis & node
			AxisNode an = q.remove();
			levelList.add(an);
			int axis = an.axis;
			TreeNode node = an.node;
 
			if(!axesMap.containsKey(axis))
				axesMap.put(axis, new LinkedList<>());
 
			if(node.left != null) q.add(new AxisNode(axis - 1, node.left));
			if(node.right != null) q.add(new AxisNode(axis + 1, node.right));
		}
		Collections.sort(levelList, Comparator.comparingInt(an -> an.node.val));
		for(AxisNode an : levelList) axesMap.get(an.axis).add(an.node.val);
	}
 
	// return arraylist of sorted map
	return new ArrayList<>(axesMap.values());
}