Diagonal Traversal of Binary Tree

Problem Statement
Given a binary tree containing nodes, consider diagonals (lines with a slope of ) passing between the nodes and print all the diagonal elements in the binary tree belonging to the same line.
Note: The diagonals with a slope of angle, will be like a .
This question has been asked in interviews with Amazon and DE Shaw.
To understand this question better, look at the examples in the below sections.
Example 1
Input
Output
Explanation
The diagonal traversal of the given tree is:

As we can see in the above image, the red lines are the diagonals of the binary tree, and the nodes between them are diagonal nodes. Printing them in the diagonal fashion will result in this order: .
Example 2
Input
Output
Explanation
The diagonal traversal of the given tree is:

As we can see in the above image, the red lines are the diagonals of the binary tree, and the nodes between them are diagonal nodes. Printing them in the diagonal fashion will result in this order: .
Constraints
The number of nodes in the binary tree should be less than .
Algorithm 1 - Recursive Approach (Hashing)
In this recursive approach, we will use hashing. The idea is to create an empty hashtable diagonalPrint, where each key in the map represents a diagonal in the binary tree (numbering from 0), and its value is a list that contains all the nodes present in the diagonal in sequential order. We will then perform preorder traversal on the tree to update the map. For each node, recur for its left subtree by increasing the diagonal d by one and recur for the right subtree with the same diagonal d.
Steps of the Algorithm
Steps inside the diagonalTraversal() function:
- Initialize an array list ans. (To store the answer, i.e., the diagonal elements of the binary tree)
- Initialize a hashtable diagonalPrint. (To store the diagonal no. as key and the list of elements in that diagonal as a value)
- Calling the diagonalTraversalUtil() function by passing of the binary tree, 0 (first diagonal no.), and diagonalPrint hashtable. (diagonalTraversalUtil() is a recursive function used to get the diagonal elements of the binary tree)
- Copy the values inside the array list of the hashtable to the ans array list.
- Return the array list ans. (Returning the array list ans which contains all the diagonal elements of the given binary tree in sequence)
Steps inside the diagonalTraversalUtil() function:
- Check if the is NULL, if yes, return. (Base case)
- Insert the diagonal's elements into the list of the hashmap. (Adding the elements of the same diagonal)
- Recursively call the function diagonalTraversalUtil() by passing , and the hashtable diagonalPrint. (To move to another diagonal by incrementing by )
- Recursively call the function diagonalTraversalUtil() by passing , and the hashtable diagonalPrint. (To move to another element of the same diagonal)
Implementation (in C++ 20, Java SE 18, and Python 3)
Implementing the recursive approach to print the diagonal elements of a given binary tree in C++, Java, and Python.
C++ 20 Implementation
Java SE 18 Implementation
Python 3 Implementation
Output
Explanation
In this algorithm, we are passing the root of the binary tree to the diagonalTraversal() function, which calls the recursive function diagonalTraversalUtil(). The function adds the diagonal elements into the hashmap in which key is the no. of the diagonal and the value is the list of elements in that diagonal.
The diagonal traversal of the given tree is:

As we can see in the above image, the red lines are the diagonals of the binary tree, and the nodes between them are diagonal nodes. Printing them in the diagonal fashion will result in this order: .
Complexity Analysis
Time Complexity: O(n) We are visiting each node in the binary tree once, so the time complexity of this algorithm will be .
Space Complexity: O(n) A hashmap is used to store the no. of diagonals and elements in diagonals using a list, therefore, the total space taken by the hashmap will be . Therefore, the space complexity of the algorithm will be O(n).
Algorithm 2 - Iterative Approach (Using Queue)
In this iterative approach, we will use a Queue data structure. The idea is similar to level order traversal (Breadth first traversal), but instead of storing nodes of a level, we enqueue nodes (add nodes at the back of the queue) in a diagonal and visit them later.
Steps of the Algorithm
- Initialize an array list . (To store the answer, i.e., the diagonal elements of the binary tree)
- Initialize a queue . (To store the nodes of the binary tree)
- Check if the is NULL, if yes, return . (Edge case)
- Enqueue into the queue . (The is the part of the first diagonal line)
- Run a while loop till gets empty. (If gets empty, we have reached the end of the given binary tree)
- Inside the while loop, initialize a TreeNode object and assign it to the front of the queue, and then pop the front element of the queue . (To move to the other diagonal)
- Run a nested while loop till becomes . (If is NULL, we have reached the end of the present diagonal line)
- Inside the nested while loop, check if exists, if yes, enqueue it inside the queue . Then add the element inside the array list and then assign to be . (To store the left node in the queue , add the data element inside the array, and then move to the right node)
- Return the array list . (Returning the array list which contains all the diagonal elements of the given binary tree in sequence)
Implementation (in C++ 20, Java SE 18, and Python 3)
Implementing the iterative approach to print the diagonal elements of a given binary tree in C++, Java, and Python.
C++ 20 Implementation
Java SE 18 Implementation
Python 3 Implementation
Output
The output for all these implementations will be the same as the algorithm and the binary tree used are the same.
Explanation
In this algorithm, we are passing the root of the binary tree to the function, which uses the iterative method with the help of a queue to get the diagonal elements of the given binary tree. The queue is used to store the left nodes of the binary tree (as left nodes create a new diagonal) so that we can visit them later and carry on with adding the elements of the right node (elements of the same diagonal) to the answer array/list .
The diagonal traversal of the given tree is:

As we can see in the above image, the red lines are the diagonals of the binary tree, and the nodes between them are diagonal nodes. Printing them in the diagonal fashion will result in this order: .
Complexity Analysis
Time Complexity: O(n)
It may look like the time complexity for this algorithm will be as there is a nested while loop inside another one, but we are visiting all the nodes at maximum twice (adding and removing them from the queue) so the time complexity will be .
Space Complexity: O(n)
The space complexity will be the number of diagonals of left nodes in the binary tree as we are using a queue to store them, but in the worst case, assuming there are only left nodes in the binary tree, the space of the queue will be . Therefore, the space complexity of this algorithm will be .
Conclusion
- The problem statement is to print the elements between each diagonal (consider lines of slope ) passing between the nodes of the binary tree.
- We can solve this problem using the recursive approach with the help of a hashtable.
- The time and space complexity of the recursive approach is .
- We can also solve this problem using the iterative approach with the help of a queue data structure.
- The time and space complexity of the iterative approach is .
FAQ
Q.What is a Hashtable?
A. A Hashtable is a data structure that stores elements in key-value pairs where keys are used for accessing the values.
They are generally unordered and are called HashMap in Java, unordered_map in C++, and dictionary in Python. An ordered Hashtable is called a map in C++ and OrderedDict in Python.
To learn more about Hashing and Hashtables, click here.
Q.What is a Queue Data Structure?
A. A Queue is a linear data structure that follows the FIFO (First In First Out) order. The deletion of an element is done from the front of the queue and the insertion of an element is done at the back of the queue. A real example of a queue data structure is a queue of people to buy movie tickets, people will join back the queue from the back and leave the queue from the front.
To learn more about the Queue data structure, click here.
Q.What is Recursion?
A. Recursion is a process in which a function calls itself directly or indirectly. The function that calls itself is called a recursive function. Recursion is used for many problems like Tree traversal (like we just did in this article), Depth-First search of a Graph, Tower of Hanoi, etc.
To learn more about recursion as well as learn about backtracking, click here.
Q.What is a Binary Tree?
A. A Binary Tree is a tree data structure in which each node has at most two children nodes, which are referred to as the left child node and the right child node. An empty tree is also considered a valid Binary Tree.
To learn more about Binary Trees, click here.
Q.What are Different Possible Traversals for Binary Trees?
A. The different possible ways of traversal of a Binary Tree are: Depth First Traversal (In-order, Pre-order, and Post-order), Breadth First Traversal, and Diagonal Traversal (Positive and Negative Slope).
Let us understand this using an example:

Pre-order Traversal: In-order Traversal: Post-order Traversal: Bread First Traversal: Positive Slope Diagonal Traversal: Negative Slope Diagonal Traversal:
To learn more about traversal of Binary Tree, click here.
Q.What if the Slope of the Diagonals were 1 and not -1?
A. If the slope of the diagonal was 1 instead of -1, the diagonals on the binary tree will look like this,

In the above image, the negative slope diagonal traversal of the binary tree above will be .
To change the given code in this article for diagonal of slope , just replace the node with the node and vice-versa.