Consider lines of slope -1 passing between nodes (dotted lines in below diagram). The diagonal sum in a binary tree is the sum of all node’s data lying between these lines. Given a Binary Tree, print all diagonal sums.
For the following input tree, the output should be 9, 19, 42.
9 is sum of 1, 3 and 5.
19 is sum of 2, 6, 4 and 7.
42 is sum of 9, 10, 11 and 12.

Algorithm:
The idea is to keep track of vertical distance from top diagonal passing through the root. We increment the vertical distance we go down to next diagonal.
- Add root with vertical distance as 0 to the queue.
- Process the sum of all right child and right of the right child and so on.
- Add left child current node into the queue for later processing. The vertical distance of the left child is the vertical distance of current node plus 1.
- Keep doing 2nd, 3rd and 4th step till the queue is empty.
Following is the implementation of the above idea.
C++
#include <bits/stdc++.h>
using namespace std;
struct Node
{
int data;
struct Node* left;
struct Node* right;
};
struct Node* newNode( int data)
{
struct Node* Node =
( struct Node*) malloc ( sizeof ( struct Node));
Node->data = data;
Node->left = Node->right = NULL;
return Node;
}
void diagonalSumUtil( struct Node* root,
int vd, map< int , int > &diagonalSum)
{
if (!root)
return ;
diagonalSum[vd] += root->data;
diagonalSumUtil(root->left, vd + 1, diagonalSum);
diagonalSumUtil(root->right, vd, diagonalSum);
}
void diagonalSum( struct Node* root)
{
map< int , int > diagonalSum;
diagonalSumUtil(root, 0, diagonalSum);
map< int , int >::iterator it;
cout << "Diagonal sum in a binary tree is - " ;
for (it = diagonalSum.begin();
it != diagonalSum.end(); ++it)
{
cout << it->second << " " ;
}
}
int main()
{
struct Node* root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(9);
root->left->right = newNode(6);
root->right->left = newNode(4);
root->right->right = newNode(5);
root->right->left->right = newNode(7);
root->right->left->left = newNode(12);
root->left->right->left = newNode(11);
root->left->left->right = newNode(10);
diagonalSum(root);
return 0;
}
|
Java
import java.util.*;
import java.util.Map.Entry;
class TreeNode
{
int data;
int vd;
TreeNode left, right;
public TreeNode( int data)
{
this .data = data;
vd = Integer.MAX_VALUE;
left = right = null ;
}
}
class Tree
{
TreeNode root;
public Tree(TreeNode root) { this .root = root; }
public void diagonalSum()
{
Queue<TreeNode> queue = new LinkedList<TreeNode>();
Map<Integer, Integer> map = new TreeMap<>();
root.vd = 0 ;
queue.add(root);
while (!queue.isEmpty())
{
TreeNode curr = queue.remove();
int vd = curr.vd;
while (curr != null )
{
int prevSum = (map.get(vd) == null )? 0 : map.get(vd);
map.put(vd, prevSum + curr.data);
if (curr.left != null )
{
curr.left.vd = vd+ 1 ;
queue.add(curr.left);
}
curr = curr.right;
}
}
Set<Entry<Integer, Integer>> set = map.entrySet();
Iterator<Entry<Integer, Integer>> iterator = set.iterator();
System.out.print( "Diagonal sum in a binary tree is - " );
while (iterator.hasNext())
{
Map.Entry<Integer, Integer> me = iterator.next();
System.out.print(me.getValue()+ " " );
}
}
}
public class DiagonalSum
{
public static void main(String[] args)
{
TreeNode root = new TreeNode( 1 );
root.left = new TreeNode( 2 );
root.right = new TreeNode( 3 );
root.left.left = new TreeNode( 9 );
root.left.right = new TreeNode( 6 );
root.right.left = new TreeNode( 4 );
root.right.right = new TreeNode( 5 );
root.right.left.left = new TreeNode( 12 );
root.right.left.right = new TreeNode( 7 );
root.left.right.left = new TreeNode( 11 );
root.left.left.right = new TreeNode( 10 );
Tree tree = new Tree(root);
tree.diagonalSum();
}
}
|
Python3
class newNode:
def __init__( self , data):
self .data = data
self .left = self .right = None
def diagonalSumUtil(root, vd, diagonalSum) :
if ( not root):
return
if vd not in diagonalSum:
diagonalSum[vd] = 0
diagonalSum[vd] + = root.data
diagonalSumUtil(root.left, vd + 1 ,
diagonalSum)
diagonalSumUtil(root.right, vd,
diagonalSum)
def diagonalSum(root) :
diagonalSum = dict ()
diagonalSumUtil(root, 0 , diagonalSum)
print ( "Diagonal sum in a binary tree is - " ,
end = "")
for it in diagonalSum:
print (diagonalSum[it], end = " " )
if __name__ = = '__main__' :
root = newNode( 1 )
root.left = newNode( 2 )
root.right = newNode( 3 )
root.left.left = newNode( 9 )
root.left.right = newNode( 6 )
root.right.left = newNode( 4 )
root.right.right = newNode( 5 )
root.right.left.right = newNode( 7 )
root.right.left.left = newNode( 12 )
root.left.right.left = newNode( 11 )
root.left.left.right = newNode( 10 )
diagonalSum(root)
|
C#
using System;
using System.Collections.Generic;
public
class TreeNode
{
public
int data;
public
int vd;
public
TreeNode left, right;
public TreeNode( int data)
{
this .data = data;
vd = int .MaxValue;
left = right = null ;
}
}
public class Tree
{
TreeNode root;
public Tree(TreeNode root)
{
this .root = root;
}
public void diagonalSum()
{
Queue<TreeNode> queue = new Queue<TreeNode>();
Dictionary< int , int > map = new Dictionary< int , int >();
root.vd = 0;
queue.Enqueue(root);
while (queue.Count != 0)
{
TreeNode curr = queue.Dequeue();
int vd = curr.vd;
while (curr != null )
{
int prevSum;
if (!map.ContainsKey(vd))
prevSum = 0;
else
prevSum = map[vd];
if (map.ContainsKey(vd))
map[vd] = prevSum + curr.data;
else
map.Add(vd, prevSum + curr.data);
if (curr.left != null )
{
curr.left.vd = vd + 1;
queue.Enqueue(curr.left);
}
curr = curr.right;
}
}
Console.Write( "Diagonal sum in a binary tree is - " );
foreach (KeyValuePair< int , int > iterator in map)
{
Console.Write(iterator.Value + " " );
}
}
}
public class DiagonalSum
{
public static void Main(String[] args)
{
TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(9);
root.left.right = new TreeNode(6);
root.right.left = new TreeNode(4);
root.right.right = new TreeNode(5);
root.right.left.left = new TreeNode(12);
root.right.left.right = new TreeNode(7);
root.left.right.left = new TreeNode(11);
root.left.left.right = new TreeNode(10);
Tree tree = new Tree(root);
tree.diagonalSum();
}
}
|
Javascript
<script>
class TreeNode {
constructor(data) {
this .data = data;
this .vd = 2147483647;
this .left = null ;
this .right = null ;
}
}
class Tree {
constructor(root) {
this .root = root;
}
diagonalSum() {
var queue = [];
var map = {};
this .root.vd = 0;
queue.push( this .root);
while (queue.length != 0) {
var curr = queue.shift();
var vd = curr.vd;
while (curr != null ) {
var prevSum;
if (!map.hasOwnProperty(vd))
prevSum = 0;
else prevSum = map[vd];
if (map.hasOwnProperty(vd))
map[vd] = prevSum + curr.data;
else
map[vd] = prevSum + curr.data;
if (curr.left != null ) {
curr.left.vd = vd + 1;
queue.push(curr.left);
}
curr = curr.right;
}
}
document.write( "Diagonal sum in a binary tree is - " );
for (const [key, value] of Object.entries(map)) {
document.write(value + " " );
}
}
}
var root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.left.left = new TreeNode(9);
root.left.right = new TreeNode(6);
root.right.left = new TreeNode(4);
root.right.right = new TreeNode(5);
root.right.left.left = new TreeNode(12);
root.right.left.right = new TreeNode(7);
root.left.right.left = new TreeNode(11);
root.left.left.right = new TreeNode(10);
var tree = new Tree(root);
tree.diagonalSum();
</script>
|
Output
Diagonal sum in a binary tree is - 9 19 42
Time Complexity: O(n)
As every node is visited just once.
Auxiliary Space: O(h+d)
Here h is the height of the tree and d is the number of diagonals. The extra space is required for recursion call stack and to store the diagonal sum in the map. In the worst case(left skewed tree) this can go upto O(n).
Exercise:
This problem was for diagonals from top to bottom and slope -1. Try the same problem for slope +1.
Method 2:
The idea behind this method is inspired by the diagonal relation in matrices. We can observe that all the elements lying on the same diagonal in a matrix have their difference of row and column same. For instance, consider the main diagonal in a square matrix, we can observe the difference of the respective row and column indices of each element on diagonal is same, i.e. each element on the main diagonal have the difference of row and column 0, eg: 0-0, 1-1, 2-2,…n-n.
Similarly, every diagonal has its own unique difference of rows and column, and with the help of this, we can identify each element, that to which diagonal it belongs.
The same idea is applied to solve this problem-
- We will treat the level of the tree nodes as their row indices, and width of the tree nodes as their column indices.
- We will denote the cell of each node as (level, width)
Example- (Taking the same tree as above)
Nodes |
Level Index |
Width Index |
1
|
0 |
0 |
2
|
1 |
-1 |
3
|
1 |
1 |
4
|
2 |
0 |
5
|
2 |
2 |
6
|
2 |
0 |
7
|
3 |
1 |
9
|
2 |
-2 |
10
|
3 |
-1 |
11
|
3 |
-1 |
12
|
3 |
-1 |
To help you visualize let’s draw a matrix, the first row and first column, are respective width and level indices-
|
-2 |
-1
|
0 |
1 |
2 |
0 |
|
|
1 |
|
|
1 |
|
2
|
|
3 |
|
2 |
9 |
|
6+4 |
|
5 |
3 |
|
10+11+12 |
|
7 |
|
Below is the implementation of the above idea:
C++
#include <bits/stdc++.h>
using namespace std;
struct Node {
int data;
Node *left, *right;
};
map< int , int > grid;
struct Node* newNode( int data)
{
struct Node* Node
= ( struct Node*) malloc ( sizeof ( struct Node));
Node->data = data;
Node->left = Node->right = NULL;
return Node;
}
void addConsideringGrid(Node* root, int level, int index)
{
if (root == NULL)
return ;
grid[level - index] += (root->data);
addConsideringGrid(root->left, level + 1, index - 1);
addConsideringGrid(root->right, level + 1, index + 1);
}
vector< int > diagonalSum(Node* root)
{
grid.clear();
addConsideringGrid(root, 0, 0);
vector< int > ans;
for ( auto x : grid) {
ans.push_back(x.second);
}
return ans;
}
int main()
{
struct Node* root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(9);
root->left->right = newNode(6);
root->right->left = newNode(4);
root->right->right = newNode(5);
root->right->left->right = newNode(7);
root->right->left->left = newNode(12);
root->left->right->left = newNode(11);
root->left->left->right = newNode(10);
vector< int > v = diagonalSum(root);
for ( int i = 0; i < v.size(); i++)
cout << v[i] << " " ;
return 0;
}
|
Java
import java.util.*;
class GFG
{
static class Node
{
int data;
Node left, right;
};
static HashMap<Integer,Integer> grid = new HashMap<>();
static Node newNode( int data)
{
Node Node = new Node();
Node.data = data;
Node.left = Node.right = null ;
return Node;
}
static void addConsideringGrid(Node root, int level, int index)
{
if (root == null )
return ;
if (grid.containsKey(level-index))
grid.put(level - index,grid.get(level-index) + (root.data));
else
grid.put(level-index, root.data);
addConsideringGrid(root.left, level + 1 , index - 1 );
addConsideringGrid(root.right, level + 1 , index + 1 );
}
static Vector<Integer> diagonalSum(Node root)
{
grid.clear();
addConsideringGrid(root, 0 , 0 );
Vector<Integer> ans = new Vector<>();
for (Map.Entry<Integer,Integer> x : grid.entrySet())
{
ans.add(x.getValue());
}
return ans;
}
public static void main(String[] args)
{
Node root = newNode( 1 );
root.left = newNode( 2 );
root.right = newNode( 3 );
root.left.left = newNode( 9 );
root.left.right = newNode( 6 );
root.right.left = newNode( 4 );
root.right.right = newNode( 5 );
root.right.left.right = newNode( 7 );
root.right.left.left = newNode( 12 );
root.left.right.left = newNode( 11 );
root.left.left.right = newNode( 10 );
Vector<Integer> v = diagonalSum(root);
for ( int i = 0 ; i < v.size(); i++)
System.out.print(v.get(i) + " " );
}
}
|
Python3
from collections import deque
class Node:
def __init__( self , key):
self .data = key
self .left = None
self .right = None
grid = {}
def addConsideringGrid(root, level, index):
global grid
if (root = = None ):
return
grid[level - index] = (grid.get(level - index, 0 ) +
root.data)
addConsideringGrid(root.left, level + 1 ,
index - 1 )
addConsideringGrid(root.right, level + 1 ,
index + 1 )
def diagonalSum(root):
addConsideringGrid(root, 0 , 0 )
ans = []
for x in grid:
ans.append(grid[x])
return ans
if __name__ = = '__main__' :
root = Node( 1 )
root.left = Node( 2 )
root.right = Node( 3 )
root.left.left = Node( 9 )
root.left.right = Node( 6 )
root.right.left = Node( 4 )
root.right.right = Node( 5 )
root.right.left.right = Node( 7 )
root.right.left.left = Node( 12 )
root.left.right.left = Node( 11 )
root.left.left.right = Node( 10 )
v = diagonalSum(root)
for i in v:
print (i, end = " " )
|
C#
using System;
using System.Collections.Generic;
public class GFG
{
public
class Node
{
public
int data;
public
Node left, right;
};
static Dictionary< int , int > grid = new Dictionary< int , int >();
static Node newNode( int data)
{
Node Node = new Node();
Node.data = data;
Node.left = Node.right = null ;
return Node;
}
static void addConsideringGrid(Node root, int level, int index)
{
if (root == null )
return ;
if (grid.ContainsKey(level - index))
grid[level - index] = grid[level - index] + (root.data);
else
grid.Add(level-index, root.data);
addConsideringGrid(root.left, level + 1, index - 1);
addConsideringGrid(root.right, level + 1, index + 1);
}
static List< int > diagonalSum(Node root)
{
grid.Clear();
addConsideringGrid(root, 0, 0);
List< int > ans = new List< int >();
foreach (KeyValuePair< int , int > x in grid)
{
ans.Add(x.Value);
}
return ans;
}
public static void Main(String[] args)
{
Node root = newNode(1);
root.left = newNode(2);
root.right = newNode(3);
root.left.left = newNode(9);
root.left.right = newNode(6);
root.right.left = newNode(4);
root.right.right = newNode(5);
root.right.left.right = newNode(7);
root.right.left.left = newNode(12);
root.left.right.left = newNode(11);
root.left.left.right = newNode(10);
List< int > v = diagonalSum(root);
for ( int i = 0; i < v.Count; i++)
Console.Write(v[i] + " " );
}
}
|
Javascript
<script>
class Node
{
constructor(data)
{
this .data=data;
this .left= null ;
this .right= null ;
}
}
let grid = new Map();
function addConsideringGrid(root,level,index)
{
if (root == null )
return ;
if (grid.has(level-index))
{
grid.set(level - index,grid.get(level-index) +
(root.data));
}
else
{
grid.set(level-index, root.data);
}
addConsideringGrid(root.left, level + 1, index - 1);
addConsideringGrid(root.right, level + 1, index + 1);
}
function diagonalSum(root)
{
addConsideringGrid(root, 0, 0);
let ans = [];
for (let [key, value] of grid)
{
ans.push(value);
}
return ans;
}
let root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(9);
root.left.right = new Node(6);
root.right.left = new Node(4);
root.right.right = new Node(5);
root.right.left.right = new Node(7);
root.right.left.left = new Node(12);
root.left.right.left = new Node(11);
root.left.left.right = new Node(10);
let v = diagonalSum(root);
for (let i = 0; i < v.length; i++)
document.write(v[i] + " " );
</script>
|
Time Complexity- O(n)
As every node is visited just once.
Auxiliary Space: O(h+d)
Here h is the height of the tree and d is the number of diagonals. The extra space is required for recursion call stack and to store the diagonal sum in the map. In the worst case(left skewed tree) this can go upto O(n).
Method – 3
No Need to used Map for extra space.
space – o(n), queue used for left node left element for later processing
Time Complexity – o(n)
C++
#include<bits/stdc++.h>
using namespace std;
struct Node
{
int data;
Node *left,*right;
};
Node* newNode( int data)
{
Node* node = new Node();
node->data = data;
node->left = node->right = NULL;
return node;
}
vector< int > diagonalSum(Node* root){
vector< int >list;
queue<Node*>Queue;
int sum = 0;
int count = 0;
int last = 0;
while (root != NULL)
{
if (root->left != NULL)
{
Queue.push(root->left);
count++;
}
sum += root->data;
root = root->right;
if (root == NULL){
if (!Queue.empty()){
root = Queue.front();
Queue.pop();
}
if (last == 0){
list.push_back(sum);
sum = 0;
last = count;
count = 0;
}
last--;
}
}
return list;
}
int main()
{
Node* root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(9);
root->left->right = newNode(6);
root->right->left = newNode(4);
root->right->right = newNode(5);
root->right->left->right = newNode(7);
root->right->left->left = newNode(12);
root->left->right->left = newNode(11);
root->left->left->right = newNode(10);
vector< int >v = diagonalSum(root);
for ( int i = 0; i < v.size(); i++)
cout << v[i] << " " ;
}
|
Java
import java.util.*;
class GFG {
static class Node {
int data;
Node left, right;
};
static Node newNode( int data)
{
Node Node = new Node();
Node.data = data;
Node.left = Node.right = null ;
return Node;
}
public static ArrayList<Integer> diagonalSum(Node root)
{
ArrayList<Integer> list = new ArrayList<Integer>();
Queue<Node> queue = new LinkedList<Node>();
int sum = 0 ;
int count = 0 ;
int last = 0 ;
while (root != null ) {
if (root.left != null ) {
queue.add(root.left);
count++;
}
sum += root.data;
root = root.right;
if (root == null ) {
if (!queue.isEmpty()) {
root = queue.poll();
}
if (last
== 0 ) {
list.add(sum);
sum = 0 ;
last = count;
count = 0 ;
}
last--;
}
}
return list;
}
public static void main(String[] args)
{
Node root = newNode( 1 );
root.left = newNode( 2 );
root.right = newNode( 3 );
root.left.left = newNode( 9 );
root.left.right = newNode( 6 );
root.right.left = newNode( 4 );
root.right.right = newNode( 5 );
root.right.left.right = newNode( 7 );
root.right.left.left = newNode( 12 );
root.left.right.left = newNode( 11 );
root.left.left.right = newNode( 10 );
ArrayList<Integer> v = diagonalSum(root);
for ( int i = 0 ; i < v.size(); i++)
System.out.print(v.get(i) + " " );
}
}
|
Python3
from collections import deque
class Node:
def __init__( self , key):
self .data = key
self .left = None
self .right = None
def diagonalSum(root):
list = []
queue = []
sum = 0
count = 0
last = 0
while (root ! = None ):
if (root.left ! = None ):
queue.append(root.left)
count + = 1
sum + = root.data
root = root.right
if (root = = None ):
if ( len (queue) ! = 0 ):
root = queue.pop( 0 )
if (last = = 0 ):
list .append( sum )
sum = 0
last = count
count = 0
last - = 1
return list
if __name__ = = '__main__' :
root = Node( 1 )
root.left = Node( 2 )
root.right = Node( 3 )
root.left.left = Node( 9 )
root.left.right = Node( 6 )
root.right.left = Node( 4 )
root.right.right = Node( 5 )
root.right.left.right = Node( 7 )
root.right.left.left = Node( 12 )
root.left.right.left = Node( 11 )
root.left.left.right = Node( 10 )
v = diagonalSum(root)
for i in v:
print (i, end = " " )
|
C#
using System;
using System.Collections.Generic;
public class GFG {
public class Node {
public int data;
public Node left, right;
};
static Node newNode( int data)
{
Node Node = new Node();
Node.data = data;
Node.left = Node.right = null ;
return Node;
}
static List< int > diagonalSum(Node root)
{
List< int > list = new List< int >();
Queue<Node> queue = new Queue<Node>();
int sum = 0;
int count = 0;
int last = 0;
while (root != null ) {
if (root.left != null ) {
queue.Enqueue(root.left);
count++;
}
sum += root.data;
root = root.right;
if (root == null ) {
if (queue.Count
!= 0) {
root = queue.Dequeue();
}
if (last
== 0) {
list.Add(sum);
sum = 0;
last = count;
count = 0;
}
last--;
}
}
return list;
}
public static void Main(String[] args)
{
Node root = newNode(1);
root.left = newNode(2);
root.right = newNode(3);
root.left.left = newNode(9);
root.left.right = newNode(6);
root.right.left = newNode(4);
root.right.right = newNode(5);
root.right.left.right = newNode(7);
root.right.left.left = newNode(12);
root.left.right.left = newNode(11);
root.left.left.right = newNode(10);
List< int > v = diagonalSum(root);
for ( int i = 0; i < v.Count; i++)
Console.Write(v[i] + " " );
}
}
|
Javascript
<script>
class Node
{
constructor(data = 0,left = null ,right = null ){
this .data = data;
this .left = this .right = null ;
}
}
function newNode(data)
{
let node = new Node();
node.data = data;
node.left = node.right = null ;
return node;
}
function diagonalSum(root){
let list = [];
let Queue = [];
let sum = 0;
let count = 0;
let last = 0;
while (root != null )
{
if (root.left != null )
{
Queue.push(root.left);
count++;
}
sum += root.data;
root = root.right;
if (root == null ){
if (Queue.length > 0){
root = Queue.shift();
}
if (last == 0){
list.push(sum);
sum = 0;
last = count;
count = 0;
}
last--;
}
}
return list;
}
let root = newNode(1);
root.left = newNode(2);
root.right = newNode(3);
root.left.left = newNode(9);
root.left.right = newNode(6);
root.right.left = newNode(4);
root.right.right = newNode(5);
root.right.left.right = newNode(7);
root.right.left.left = newNode(12);
root.left.right.left = newNode(11);
root.left.left.right = newNode(10);
let v = diagonalSum(root);
for (let i = 0; i < v.length; i++)
document.write(v[i] + " " );
</script>
|
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
11 Jul, 2022
Like Article
Save Article