Question: Given an arbitrary binary tree, convert it to a binary tree that holds Children Sum Property. You can only increment data values in any node (You cannot change the structure of the tree and cannot decrement the value of any node).
For example, the below tree doesn’t hold the children sum property, convert it to a tree that holds the property.
50
/ \
/ \
7 2
/ \ /\
/ \ / \
3 5 1 30
Algorithm: Traverse the given tree in post order to convert it, i.e., first change left and right children to hold the children sum property then change the parent node.
Let difference between node’s data and children sum be diff.
diff = node’s children sum - node’s data
If diff is 0 then nothing needs to be done.
If diff > 0 ( node’s data is smaller than node’s children sum) increment the node’s data by diff.
If diff < 0 (node’s data is greater than the node’s children sum) then increment one child’s data. We can choose to increment either left or right child if they both are not NULL. Let us always first increment the left child. Incrementing a child changes the subtree’s children sum property so we need to change left subtree also. So we recursively increment the left child. If left child is empty then we recursively call increment() for right child.
Let us run the algorithm for the given example.
First convert the left subtree (increment 7 to 8).
50
/ \
/ \
8 2
/ \ /\
/ \ / \
3 5 1 30
Then convert the right subtree (increment 2 to 31)
50
/ \
/ \
8 31
/ \ / \
/ \ / \
3 5 1 30
Now convert the root, we have to increment left subtree for converting the root.
50
/ \
/ \
19 31
/ \ / \
/ \ / \
14 5 1 30
Please note the last step – we have incremented 8 to 19, and to fix the subtree we have incremented 3 to 14.
Implementation:
C++
#include<bits/stdc++.h>
using namespace std;
class node
{
public :
int data;
node* left;
node* right;
node( int data)
{
this ->data = data;
this ->left = NULL;
this ->right = NULL;
}
};
void increment(node* node, int diff);
void convertTree(node* node)
{
int left_data = 0, right_data = 0, diff;
if (node == NULL || (node->left == NULL &&
node->right == NULL))
return ;
else
{
convertTree(node->left);
convertTree(node->right);
if (node->left != NULL)
left_data = node->left->data;
if (node->right != NULL)
right_data = node->right->data;
diff = left_data + right_data - node->data;
if (diff > 0)
node->data = node->data + diff;
if (diff < 0)
increment(node, -diff);
}
}
void increment(node* node, int diff)
{
if (node->left != NULL)
{
node->left->data = node->left->data + diff;
increment(node->left, diff);
}
else if (node->right != NULL)
{
node->right->data = node->right->data + diff;
increment(node->right, diff);
}
}
void printInorder(node* node)
{
if (node == NULL)
return ;
printInorder(node->left);
cout<<node->data<< " " ;
printInorder(node->right);
}
int main()
{
node *root = new node(50);
root->left = new node(7);
root->right = new node(2);
root->left->left = new node(3);
root->left->right = new node(5);
root->right->left = new node(1);
root->right->right = new node(30);
cout << "\nInorder traversal before conversion: " << endl;
printInorder(root);
convertTree(root);
cout << "\nInorder traversal after conversion: " << endl;
printInorder(root);
return 0;
}
|
C
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node* left;
struct node* right;
};
void increment( struct node* node, int diff);
struct node* newNode( int data);
void convertTree( struct node* node)
{
int left_data = 0, right_data = 0, diff;
if (node == NULL ||
(node->left == NULL && node->right == NULL))
return ;
else
{
convertTree(node->left);
convertTree(node->right);
if (node->left != NULL)
left_data = node->left->data;
if (node->right != NULL)
right_data = node->right->data;
diff = left_data + right_data - node->data;
if (diff > 0)
node->data = node->data + diff;
if (diff < 0)
increment(node, -diff);
}
}
void increment( struct node* node, int diff)
{
if (node->left != NULL)
{
node->left->data = node->left->data + diff;
increment(node->left, diff);
}
else if (node->right != NULL)
{
node->right->data = node->right->data + diff;
increment(node->right, diff);
}
}
void printInorder( struct node* node)
{
if (node == NULL)
return ;
printInorder(node->left);
printf ( "%d " , node->data);
printInorder(node->right);
}
struct node* newNode( int data)
{
struct node* node =
( struct node*) malloc ( sizeof ( struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return (node);
}
int main()
{
struct node *root = newNode(50);
root->left = newNode(7);
root->right = newNode(2);
root->left->left = newNode(3);
root->left->right = newNode(5);
root->right->left = newNode(1);
root->right->right = newNode(30);
printf ( "\n Inorder traversal before conversion " );
printInorder(root);
convertTree(root);
printf ( "\n Inorder traversal after conversion " );
printInorder(root);
getchar ();
return 0;
}
|
Java
class Node
{
int data;
Node left, right;
Node( int item)
{
data = item;
left = right = null ;
}
}
class BinaryTree
{
Node root;
void convertTree(Node node)
{
int left_data = 0 , right_data = 0 , diff;
if (node == null
|| (node.left == null && node.right == null ))
return ;
else
{
convertTree(node.left);
convertTree(node.right);
if (node.left != null )
left_data = node.left.data;
if (node.right != null )
right_data = node.right.data;
diff = left_data + right_data - node.data;
if (diff > 0 )
node.data = node.data + diff;
if (diff < 0 )
increment(node, -diff);
}
}
void increment(Node node, int diff)
{
if (node.left != null )
{
node.left.data = node.left.data + diff;
increment(node.left, diff);
}
else if (node.right != null )
{
node.right.data = node.right.data + diff;
increment(node.right, diff);
}
}
void printInorder(Node node)
{
if (node == null )
return ;
printInorder(node.left);
System.out.print(node.data + " " );
printInorder(node.right);
}
public static void main(String args[])
{
BinaryTree tree = new BinaryTree();
tree.root = new Node( 50 );
tree.root.left = new Node( 7 );
tree.root.right = new Node( 2 );
tree.root.left.left = new Node( 3 );
tree.root.left.right = new Node( 5 );
tree.root.right.left = new Node( 1 );
tree.root.right.right = new Node( 30 );
System.out.println( "Inorder traversal before conversion is :" );
tree.printInorder(tree.root);
tree.convertTree(tree.root);
System.out.println( "" );
System.out.println( "Inorder traversal after conversion is :" );
tree.printInorder(tree.root);
}
}
|
Python3
class newNode:
def __init__( self , key):
self .data = key
self .left = None
self .right = None
def convertTree(node):
left_data = 0
right_data = 0
diff = 0
if (node = = None or (node.left = = None and
node.right = = None )):
return
else :
convertTree(node.left)
convertTree(node.right)
if (node.left ! = None ):
left_data = node.left.data
if (node.right ! = None ):
right_data = node.right.data
diff = left_data + right_data - node.data
if (diff > 0 ):
node.data = node.data + diff
if (diff < 0 ):
increment(node, - diff)
def increment(node, diff):
if (node.left ! = None ):
node.left.data = node.left.data + diff
increment(node.left, diff)
elif (node.right ! = None ):
node.right.data = node.right.data + diff
increment(node.right, diff)
def printInorder(node):
if (node = = None ):
return
printInorder(node.left)
print (node.data,end = " " )
printInorder(node.right)
if __name__ = = '__main__' :
root = newNode( 50 )
root.left = newNode( 7 )
root.right = newNode( 2 )
root.left.left = newNode( 3 )
root.left.right = newNode( 5 )
root.right.left = newNode( 1 )
root.right.right = newNode( 30 )
print ( "Inorder traversal before conversion" )
printInorder(root)
convertTree(root)
print ( "\nInorder traversal after conversion " )
printInorder(root)
|
C#
using System;
public class Node
{
public int data;
public Node left, right;
public Node( int item)
{
data = item;
left = right = null ;
}
}
class GFG
{
public Node root;
public virtual void convertTree(Node node)
{
int left_data = 0, right_data = 0, diff;
if (node == null || (node.left == null &&
node.right == null ))
{
return ;
}
else
{
convertTree(node.left);
convertTree(node.right);
if (node.left != null )
{
left_data = node.left.data;
}
if (node.right != null )
{
right_data = node.right.data;
}
diff = left_data + right_data - node.data;
if (diff > 0)
{
node.data = node.data + diff;
}
if (diff < 0)
{
increment(node, -diff);
}
}
}
public virtual void increment(Node node, int diff)
{
if (node.left != null )
{
node.left.data = node.left.data + diff;
increment(node.left, diff);
}
else if (node.right != null )
{
node.right.data = node.right.data + diff;
increment(node.right, diff);
}
}
public virtual void printInorder(Node node)
{
if (node == null )
{
return ;
}
printInorder(node.left);
Console.Write(node.data + " " );
printInorder(node.right);
}
public static void Main( string [] args)
{
GFG tree = new GFG();
tree.root = new Node(50);
tree.root.left = new Node(7);
tree.root.right = new Node(2);
tree.root.left.left = new Node(3);
tree.root.left.right = new Node(5);
tree.root.right.left = new Node(1);
tree.root.right.right = new Node(30);
Console.WriteLine( "Inorder traversal " +
"before conversion is :" );
tree.printInorder(tree.root);
tree.convertTree(tree.root);
Console.WriteLine( "" );
Console.WriteLine( "Inorder traversal " +
"after conversion is :" );
tree.printInorder(tree.root);
}
}
|
Javascript
<script>
class Node
{
constructor(data) {
this .left = null ;
this .right = null ;
this .data = data;
}
}
let root;
function convertTree(node)
{
let left_data = 0, right_data = 0, diff;
if (node == null
|| (node.left == null && node.right == null ))
return ;
else
{
convertTree(node.left);
convertTree(node.right);
if (node.left != null )
left_data = node.left.data;
if (node.right != null )
right_data = node.right.data;
diff = left_data + right_data - node.data;
if (diff > 0)
node.data = node.data + diff;
if (diff < 0)
increment(node, -diff);
}
}
function increment(node, diff)
{
if (node.left != null )
{
node.left.data = node.left.data + diff;
increment(node.left, diff);
}
else if (node.right != null )
{
node.right.data = node.right.data + diff;
increment(node.right, diff);
}
}
function printInorder(node)
{
if (node == null )
return ;
printInorder(node.left);
document.write(node.data + " " );
printInorder(node.right);
}
root = new Node(50);
root.left = new Node(7);
root.right = new Node(2);
root.left.left = new Node(3);
root.left.right = new Node(5);
root.right.left = new Node(1);
root.right.right = new Node(30);
document.write( "Inorder traversal before conversion is :" +
"</br>" );
printInorder(root);
convertTree(root);
document.write( "</br>" );
document.write( "Inorder traversal after conversion is :" +
"</br>" );
printInorder(root);
</script>
|
OutputInorder traversal before conversion:
3 7 5 50 1 2 30
Inorder traversal after conversion:
14 19 5 50 1 31 30
Time Complexity: O(n^2), Worst case complexity is for a skewed tree such that nodes are in decreasing order from root to leaf.
Space Complexity: O(h) where h is the height of the binary tree.
Please write comments if you find any bug in the above algorithm or a better way to solve the same problem.
METHOD-2: Most Optimized Solution: (Linear Time)
The idea is to fix the children in top-down fashion of Tree,
and fix the children sum property in bottom-up fashion of Tree
Algorithm:
50
/ \
/ \
7 2
/ \ /\
/ \ / \
3 5 1 30
Here, the issue is having shortage while summing, eg – 1+30 =31 then 3+5 = 8 => 31+8 =39, but u cannot decrement 50 to 39 as per rule.
So while going down the tree increase the value so to make sure we don’t end up with shortage.
Then all we need to do is, while returning, just sum the children and replace the parent node.
At last, the Children sum property holds TRUE. (As there is no restriction on the value needs to be minimum as such)
CODE:
C++
#include<bits/stdc++.h>
using namespace std;
class node
{
public :
int data;
node* left;
node* right;
node( int data)
{
this ->data = data;
this ->left = NULL;
this ->right = NULL;
}
};
void printInorder(node* node)
{
if (node == NULL)
return ;
printInorder(node->left);
cout<<node->data<< " " ;
printInorder(node->right);
}
void convertTree(node* root){
if (root == NULL) return ;
int childSum = 0;
if (root->left) childSum+=root->left->data;
if (root->right) childSum+=root->right->data;
if (childSum>=root->data){
root->data = childSum;
}
else {
if (root->left) root->left->data = root->data;
if (root->right) root->right->data = root->data;
}
convertTree(root->left);
convertTree(root->right);
int totVal = 0;
if (root->left) totVal+=root->left->data;
if (root->right) totVal+=root->right->data;
if (root->left || root->right) root->data = totVal;
}
int main()
{
node *root = new node(50);
root->left = new node(7);
root->right = new node(2);
root->left->left = new node(3);
root->left->right = new node(5);
root->right->left = new node(1);
root->right->right = new node(30);
cout << "\nInorder traversal before conversion: " << endl;
printInorder(root);
convertTree(root);
cout << "\nInorder traversal after conversion: " << endl;
printInorder(root);
return 0;
}
|
Java
import java.io.*;
class Node {
int data;
Node left, right;
Node( int data)
{
this .data = data;
left = right = null ;
}
}
class BinaryTree {
Node root;
void printInorder(Node node)
{
if (node == null )
return ;
printInorder(node.left);
System.out.print(node.data + " " );
printInorder(node.right);
}
void convertTree(Node root)
{
if (root == null )
return ;
int childSum = 0 ;
if (root.left != null )
childSum += root.left.data;
if (root.right != null )
childSum += root.right.data;
if (childSum >= root.data) {
root.data = childSum;
}
else {
if (root.left != null )
root.left.data = root.data;
if (root.right != null )
root.right.data = root.data;
}
convertTree(root.left);
convertTree(root.right);
int totVal = 0 ;
if (root.left != null )
totVal += root.left.data;
if (root.right != null )
totVal += root.right.data;
if (root.left != null || root.right != null )
root.data = totVal;
}
public static void main(String[] args)
{
BinaryTree tree = new BinaryTree();
tree.root = new Node( 50 );
tree.root.left = new Node( 7 );
tree.root.right = new Node( 2 );
tree.root.left.left = new Node( 3 );
tree.root.left.right = new Node( 5 );
tree.root.right.left = new Node( 1 );
tree.root.right.right = new Node( 30 );
System.out.print(
"Inorder traversal before conversion: " );
tree.printInorder(tree.root);
tree.convertTree(tree.root);
System.out.print(
"\nInorder traversal after conversion: " );
tree.printInorder(tree.root);
}
}
|
Python3
class Node:
def __init__( self , data):
self .data = data
self .left = None
self .right = None
def printInorder(node):
if node is None :
return
printInorder(node.left)
print (node.data, end = " " )
printInorder(node.right)
def convertTree(root):
if root is None :
return
childSum = 0
if root.left:
childSum + = root.left.data
if root.right:
childSum + = root.right.data
if childSum > = root.data:
root.data = childSum
else :
if root.left:
root.left.data = root.data
if root.right:
root.right.data = root.data
convertTree(root.left)
convertTree(root.right)
totVal = 0
if root.left:
totVal + = root.left.data
if root.right:
totVal + = root.right.data
if root.left or root.right:
root.data = totVal
if __name__ = = "__main__" :
root = Node( 50 )
root.left = Node( 7 )
root.right = Node( 2 )
root.left.left = Node( 3 )
root.left.right = Node( 5 )
root.right.left = Node( 1 )
root.right.right = Node( 30 )
print ( "Inorder traversal before conversion: " )
printInorder(root)
convertTree(root)
print ( "\nInorder traversal after conversion: " )
printInorder(root)
|
C#
using System;
public class node{
public int data;
public node left, right;
public node( int item){
data = item;
left = right = null ;
}
}
class GFG{
public node root;
public virtual void convertTree(node root){
if (root == null ) return ;
int childSum = 0;
if (root.left != null ) childSum += root.left.data;
if (root.right != null ) childSum += root.right.data;
if (childSum >= root.data){
root.data = childSum;
} else {
if (root.left != null ) root.left.data = root.data;
if (root.right != null ) root.right.data = root.data;
}
convertTree(root.left);
convertTree(root.right);
int totVal = 0;
if (root.left != null ) totVal += root.left.data;
if (root.right != null ) totVal += root.right.data;
if (root.left != null || root.right != null ) root.data = totVal;
}
public virtual void printInorder(node node){
if (node == null ) return ;
printInorder(node.left);
Console.Write(node.data + " " );
printInorder(node.right);
}
public static void Main( string [] args){
GFG tree = new GFG();
tree.root = new node(50);
tree.root.left = new node(7);
tree.root.right = new node(2);
tree.root.left.left = new node(3);
tree.root.left.right = new node(5);
tree.root.right.left = new node(1);
tree.root.right.right = new node(30);
Console.WriteLine( "Inorder traversal before conversion is :" );
tree.printInorder(tree.root);
tree.convertTree(tree.root);
Console.WriteLine( "" );
Console.WriteLine( "Inorder traversal after conversion is :" );
tree.printInorder(tree.root);
}
}
|
Javascript
class node{
constructor(data){
this .data = data;
this .left = null ;
this .right = null ;
}
}
function printInorder(node)
{
if (node == null ) return ;
printInorder(node.left);
console.log(node.data + " " );
printInorder(node.right);
}
function convertTree(root){
if (root == null ) return null ;
let childSum = 0;
if (root.left != null ) childSum += root.left.data;
if (root.right != null ) childSum += root.right.data;
if (childSum >= root.data){
root.data = childSum;
} else {
if (root.left) root.left.data = root.data;
if (root.right) root.right.data = root.data;
}
convertTree(root.left);
convertTree(root.right);
let totVal = 0;
if (root.left) totVal += root.left.data;
if (root.right) totVal += root.right.data;
if (root.left || root.right) root.data = totVal;
}
let root = new node(50);
root.left = new node(7);
root.right = new node(2);
root.left.left = new node(3);
root.left.right = new node(5);
root.right.left = new node(1);
root.right.right = new node(30);
console.log( "Inorder Traversal before conversion: " );
printInorder(root);
convertTree(root);
console.log( "Inorder Traversal after conversion: " );
printInorder(root);
|
OutputInorder traversal before conversion:
3 7 5 50 1 2 30
Inorder traversal after conversion:
50 100 50 200 50 100 50
Time Complexity: O(n) as we are doing traversal of the tree only once.
Reason :
Recurrence Relation : T(n) = 2*T(n/2) + O(1)
Space Complexity: O(ht of tree) best and avg: O(log n ) worst: O(n) Skewed trees.
Reason:
Function call stack of recursion.
Approach using DP:
In this implementation, a queue is used to perform a level-order traversal of the tree. The queue helps to process each node and its children in a breadth-first manner. The program calculates the difference between the sum of the left and right child values and the current node’s value. If the difference is positive, the current node’s value is increased by the difference. If the difference is negative, the program distributes the difference to the left or right child, depending on which child is present.
Here’s the implementation of the given program using a dynamic programming (DP) approach:
C++
#include <iostream>
#include <queue>
using namespace std;
class node
{
public :
int data;
node* left;
node* right;
node( int data)
{
this ->data = data;
this ->left = NULL;
this ->right = NULL;
}
};
void convertTree(node* root)
{
if (root == NULL || (root->left == NULL && root->right == NULL))
return ;
queue<node*> q;
q.push(root);
while (!q.empty())
{
node* current = q.front();
q.pop();
int left_data = 0, right_data = 0;
if (current->left != NULL)
{
q.push(current->left);
left_data = current->left->data;
}
if (current->right != NULL)
{
q.push(current->right);
right_data = current->right->data;
}
int diff = left_data + right_data - current->data;
if (diff > 0)
current->data += diff;
if (diff < 0)
{
if (current->left != NULL)
current->left->data += -diff;
else if (current->right != NULL)
current->right->data += -diff;
}
}
}
void printInorder(node* root)
{
if (root == NULL)
return ;
printInorder(root->left);
cout << root->data << " " ;
printInorder(root->right);
}
int main()
{
node *root = new node(50);
root->left = new node(7);
root->right = new node(2);
root->left->left = new node(3);
root->left->right = new node(5);
root->right->left = new node(1);
root->right->right = new node(30);
cout << "Inorder traversal before conversion: " ;
printInorder(root);
cout << endl;
convertTree(root);
cout << "Inorder traversal after conversion: " ;
printInorder(root);
cout << endl;
return 0;
}
|
Java
import java.util.LinkedList;
import java.util.Queue;
class Node {
int data;
Node left;
Node right;
public Node( int data) {
this .data = data;
this .left = null ;
this .right = null ;
}
}
public class BinaryTreeConversion {
public static void convertTree(Node root) {
if (root == null || (root.left == null && root.right == null ))
return ;
Queue<Node> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
Node current = queue.poll();
int leftData = 0 , rightData = 0 ;
if (current.left != null ) {
queue.add(current.left);
leftData = current.left.data;
}
if (current.right != null ) {
queue.add(current.right);
rightData = current.right.data;
}
int diff = leftData + rightData - current.data;
if (diff > 0 )
current.data += diff;
if (diff < 0 ) {
if (current.left != null )
current.left.data += -diff;
else if (current.right != null )
current.right.data += -diff;
}
}
}
public static void printInorder(Node root) {
if (root == null )
return ;
printInorder(root.left);
System.out.print(root.data + " " );
printInorder(root.right);
}
public static void main(String[] args) {
Node root = new Node( 50 );
root.left = new Node( 7 );
root.right = new Node( 2 );
root.left.left = new Node( 3 );
root.left.right = new Node( 5 );
root.right.left = new Node( 1 );
root.right.right = new Node( 30 );
System.out.print( "Inorder traversal before conversion: " );
printInorder(root);
System.out.println();
convertTree(root);
System.out.print( "Inorder traversal after conversion: " );
printInorder(root);
System.out.println();
}
}
|
Javascript
class Node {
constructor(data) {
this .data = data;
this .left = null ;
this .right = null ;
}
}
function convertTree(root) {
if (root === null || (root.left === null && root.right === null ))
return ;
const queue = [root];
while (queue.length > 0) {
const current = queue.shift();
let leftData = 0;
let rightData = 0;
if (current.left !== null ) {
queue.push(current.left);
leftData = current.left.data;
}
if (current.right !== null ) {
queue.push(current.right);
rightData = current.right.data;
}
const diff = leftData + rightData - current.data;
if (diff > 0)
current.data += diff;
if (diff < 0) {
if (current.left !== null )
current.left.data += -diff;
else if (current.right !== null )
current.right.data += -diff;
}
}
}
function printInorder(root) {
if (root === null )
return ;
printInorder(root.left);
process.stdout.write(root.data + " " );
printInorder(root.right);
}
const root = new Node(50);
root.left = new Node(7);
root.right = new Node(2);
root.left.left = new Node(3);
root.left.right = new Node(5);
root.right.left = new Node(1);
root.right.right = new Node(30);
console.log( "Inorder traversal before conversion:" );
printInorder(root);
console.log();
convertTree(root);
console.log( "Inorder traversal after conversion:" );
printInorder(root);
console.log();
|
Output:
Inorder traversal before conversion:
3 7 5 50 1 2 30
Inorder traversal after conversion:
43 48 5 50 1 31 30
Time Complexity: O(n)
Space Complexity: O(n)
The above Method-2 Idea, Algorithm, and Code are contributed by Balakrishnan R (rbkraj000 – GFG ID). If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.