Open In App

Convert an arbitrary Binary Tree to a tree that holds Children Sum Property

Improve
Improve
Like Article
Like
Save
Share
Report

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++




/* C++ Program to convert an arbitrary
binary tree to a tree that hold
children sum property */
#include<bits/stdc++.h>
using namespace std;
 
class node
{
    public:
    int data;
    node* left;
    node* right;
     
    /* Constructor that allocates a new node
    with the given data and NULL left and right
    pointers. */
    node(int data)
    {
        this->data = data;
        this->left = NULL;
        this->right = NULL;
    }
};
 
/* This function is used
to increment left subtree */
void increment(node* node, int diff);
 
/* This function changes a tree
to hold children sum property */
void convertTree(node* node)
{
    int left_data = 0, right_data = 0, diff;
     
    /* If tree is empty or it's a leaf 
        node then return true */
    if (node == NULL || (node->left == NULL &&
                        node->right == NULL))
        return;
    else
    {
        /* convert left and right subtrees */
        convertTree(node->left);
        convertTree(node->right);
     
        /* If left child is not present then 0 is used
        as data of left child */
        if (node->left != NULL)
        left_data = node->left->data;
     
        /* If right child is not present then 0 is used
        as data of right child */
        if (node->right != NULL)
        right_data = node->right->data;
     
        /* get the diff of node's data and children sum */
        diff = left_data + right_data - node->data;
     
        /* If node's children sum is
        greater than the node's data */
        if (diff > 0)
        node->data = node->data + diff;
     
        /* THIS IS TRICKY --> If node's data
        is greater than children sum,
        then increment subtree by diff */
        if (diff < 0)
        increment(node, -diff); // -diff is used to make diff positive
    }
}
 
/* This function is used
to increment subtree by diff */
void increment(node* node, int diff)
{
    /* IF left child is not
    NULL then increment it */
    if(node->left != NULL)
    {
        node->left->data = node->left->data + diff;
     
        // Recursively call to fix
        // the descendants of node->left
        increment(node->left, diff);
    }
    else if (node->right != NULL) // Else increment right child
    {
        node->right->data = node->right->data + diff;
     
        // Recursively call to fix
        // the descendants of node->right
        increment(node->right, diff);
    }
}
 
/* Given a binary tree,
printInorder() prints out its
inorder traversal*/
void printInorder(node* node)
{
    if (node == NULL)
        return;
     
    /* first recur on left child */
    printInorder(node->left);
     
    /* then print the data of node */
    cout<<node->data<<" ";
     
    /* now recur on right child */
    printInorder(node->right);
}
 
/* Driver code */
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;
}
 
// This code is contributed by rathbhupendra


Java




    // Java program to convert an arbitrary binary tree to a tree that holds
// children sum property
  
// A binary tree node
class Node
{
    int data;
    Node left, right;
  
    Node(int item)
    {
        data = item;
        left = right = null;
    }
}
  
class BinaryTree
{
    Node root;
    /* This function changes a tree to hold children sum
       property */
  
    void convertTree(Node node)
    {
        int left_data = 0, right_data = 0, diff;
  
        /* If tree is empty or it's a leaf node then
         return true */
        if (node == null
                || (node.left == null && node.right == null))
            return;
        else
        {
            /* convert left and right subtrees  */
            convertTree(node.left);
            convertTree(node.right);
        
            /* If left child is not present then 0 is used
             as data of left child */
            if (node.left != null)
                left_data = node.left.data;
             
            /* If right child is not present then 0 is used
             as data of right child */
            if (node.right != null)
                right_data = node.right.data;
  
            /* get the diff of node's data and children sum */
            diff = left_data + right_data - node.data;
  
            /* If node's children sum is greater than the node's data */
            if (diff > 0)
                node.data = node.data + diff;
  
            /* THIS IS TRICKY --> If node's data is greater than children
               sum, then increment subtree by diff */
            if (diff < 0)
             
                // -diff is used to make diff positive
                increment(node, -diff); 
        }
    }
  
    /* This function is used to increment subtree by diff */
    void increment(Node node, int diff)
    {
        /* IF left child is not NULL then increment it */
        if (node.left != null)
        {
            node.left.data = node.left.data + diff;
  
            // Recursively call to fix the descendants of node->left
            increment(node.left, diff);
        }
        else if (node.right != null) // Else increment right child
        {
            node.right.data = node.right.data + diff;
  
            // Recursively call to fix the descendants of node->right
            increment(node.right, diff);
        }
    }
  
    /* Given a binary tree, printInorder() prints out its
     inorder traversal*/
    void printInorder(Node node)
    {
        if (node == null)
            return;
             
        /* first recur on left child */
        printInorder(node.left);
  
        /* then print the data of node */
        System.out.print(node.data + " ");
  
        /* now recur on right child */
        printInorder(node.right);
    }
  
    // Driver program to test above functions
    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);
  
    }
}
 
// This code has been contributed by Mayank Jaiswal(mayank_24)


Python3




# Program to convert an arbitrary binary tree
# to a tree that holds children sum property
 
# Helper function that allocates a new
# node with the given data and None
# left and right pointers.                                    
class newNode:
 
    # Construct to create a new node
    def __init__(self, key):
        self.data = key
        self.left = None
        self.right = None
 
# This function changes a tree to
# hold children sum property
def convertTree(node):
 
    left_data = 0
    right_data = 0
    diff=0
 
    # If tree is empty or it's a
    # leaf node then return true
    if (node == None or (node.left == None and
                         node.right == None)):
        return
     
    else:
         
        """ convert left and right subtrees """
        convertTree(node.left)
        convertTree(node.right)
 
    """ If left child is not present then 0
    is used as data of left child """
    if (node.left != None):
        left_data = node.left.data
 
    """ If right child is not present then 0
    is used as data of right child """
    if (node.right != None):
        right_data = node.right.data
 
    """ get the diff of node's data
        and children sum """
    diff = left_data + right_data - node.data
 
    """ If node's children sum is greater
        than the node's data """
    if (diff > 0):
        node.data = node.data + diff
 
    """ THIS IS TRICKY -. If node's data is
    greater than children sum, then increment
    subtree by diff """
    if (diff < 0):
        increment(node, -diff) # -diff is used to
                               # make diff positive
 
""" This function is used to increment
    subtree by diff """
def increment(node, diff):
 
    """ IF left child is not None
        then increment it """
    if(node.left != None):
        node.left.data = node.left.data + diff
 
        # Recursively call to fix the
        # descendants of node.left
        increment(node.left, diff)
 
    elif(node.right != None): # Else increment right child
        node.right.data = node.right.data + diff
 
        # Recursively call to fix the
        # descendants of node.right
        increment(node.right, diff)
 
""" Given a binary tree, printInorder()
prints out its inorder traversal"""
def printInorder(node):
 
    if (node == None):
        return
 
    """ first recur on left child """
    printInorder(node.left)
 
    """ then print the data of node """
    print(node.data,end=" ")
 
    """ now recur on right child """
    printInorder(node.right)
 
# Driver Code
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)
 
# This code is contributed by
# Shubham Singh(SHUBHAMSINGH10)


C#




// C# program to convert an arbitrary
// binary tree to a tree that holds
// children sum property
using System;
 
// A binary tree node
public class Node
{
    public int data;
    public Node left, right;
 
    public Node(int item)
    {
        data = item;
        left = right = null;
    }
}
 
class GFG
{
public Node root;
 
/* This function changes a tree to
hold children sum property */
public virtual void convertTree(Node node)
{
    int left_data = 0, right_data = 0, diff;
 
    /* If tree is empty or it's a leaf
    node then return true */
    if (node == null || (node.left == null &&
                         node.right == null))
    {
        return;
    }
    else
    {
        /* convert left and right subtrees */
        convertTree(node.left);
        convertTree(node.right);
 
        /* If left child is not present then
        0 is used as data of left child */
        if (node.left != null)
        {
            left_data = node.left.data;
        }
 
        /* If right child is not present then
        0 is used as data of right child */
        if (node.right != null)
        {
            right_data = node.right.data;
        }
 
        /* get the diff of node's data
           and children sum */
        diff = left_data + right_data - node.data;
 
        /* If node's children sum is greater
           than the node's data */
        if (diff > 0)
        {
            node.data = node.data + diff;
        }
 
        /* THIS IS TRICKY --> If node's data is
        greater than children sum, then increment
        subtree by diff */
        if (diff < 0)
        {
 
            // -diff is used to make diff positive
            increment(node, -diff);
        }
    }
}
 
/* This function is used to increment
subtree by diff */
public virtual void increment(Node node, int diff)
{
    /* IF left child is not NULL then
    increment it */
    if (node.left != null)
    {
        node.left.data = node.left.data + diff;
 
        // Recursively call to fix the
        // descendants of node->left
        increment(node.left, diff);
    }
    else if (node.right != null) // Else increment right child
    {
        node.right.data = node.right.data + diff;
 
        // Recursively call to fix the
        // descendants of node->right
        increment(node.right, diff);
    }
}
 
/* Given a binary tree, printInorder()
prints out its inorder traversal*/
public virtual void printInorder(Node node)
{
    if (node == null)
    {
        return;
    }
 
    /* first recur on left child */
    printInorder(node.left);
 
    /* then print the data of node */
    Console.Write(node.data + " ");
 
    /* now recur on right child */
    printInorder(node.right);
}
 
// Driver Code
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);
}
}
 
// This code is contributed by Shrikant13


Javascript




<script>
 
      // JavaScript program to convert an arbitrary binary tree
    // to a tree that holds children sum property
     
    class Node
    {
        constructor(data) {
           this.left = null;
           this.right = null;
           this.data = data;
        }
    }
     
    let root;
    /* This function changes a tree to hold children sum
       property */
    
    function convertTree(node)
    {
        let left_data = 0, right_data = 0, diff;
    
        /* If tree is empty or it's a leaf node then
         return true */
        if (node == null
                || (node.left == null && node.right == null))
            return;
        else
        {
            /* convert left and right subtrees  */
            convertTree(node.left);
            convertTree(node.right);
          
            /* If left child is not present then 0 is used
             as data of left child */
            if (node.left != null)
                left_data = node.left.data;
               
            /* If right child is not present then 0 is used
             as data of right child */
            if (node.right != null)
                right_data = node.right.data;
    
            /* get the diff of node's data and children sum */
            diff = left_data + right_data - node.data;
    
            /* If node's children sum is greater
            than the node's data */
            if (diff > 0)
                node.data = node.data + diff;
    
            /* THIS IS TRICKY --> If node's data
               is greater than children
               sum, then increment subtree by diff */
            if (diff < 0)
               
                // -diff is used to make diff positive
                increment(node, -diff); 
        }
    }
    
    /* This function is used to increment subtree by diff */
    function increment(node, diff)
    {
        /* IF left child is not NULL then increment it */
        if (node.left != null)
        {
            node.left.data = node.left.data + diff;
    
            // Recursively call to fix the
            // descendants of node->left
            increment(node.left, diff);
        }
        else if (node.right != null) // Else increment right child
        {
            node.right.data = node.right.data + diff;
    
            // Recursively call to fix the
            // descendants of node->right
            increment(node.right, diff);
        }
    }
    
    /* Given a binary tree, printInorder() prints out its
     inorder traversal*/
    function printInorder(node)
    {
        if (node == null)
            return;
               
        /* first recur on left child */
        printInorder(node.left);
    
        /* then print the data of node */
        document.write(node.data + " ");
    
        /* now recur on right child */
        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>


Output

Inorder 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;
     
    /* first recur on left child */
    printInorder(node->left);
     
    /* then print the data of node */
    cout<<node->data<<" ";
     
    /* now recur on right child */
    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){
        //change root
        root->data = childSum;
    }
    else{
        //change both children
        if(root->left) root->left->data = root->data;
        if(root->right) root->right->data = root->data;
         
    }
     
    //now go down the tree and check others - Inorder
    convertTree(root->left);
    convertTree(root->right);
     
    //here is the backtracking part happens, as changes may happen
    int totVal = 0;
     
    if(root->left) totVal+=root->left->data;
    if(root->right) totVal+=root->right->data;
     
    // Leaf node dont update, as it will make it 0
    if(root->left || root->right) root->data = totVal;
    //So that at last the children Sum property stays TRUE
 
}
 
 
/* Driver code */
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;
}
 
//Code Done by Balakrishnan R (rbkraj000)


Java




// Java code for the above approach
import java.io.*;
 
// Java code to convert a given binary tree to
// a tree where every node contains sum of all nodes
// in left and right subtree in the original tree
class Node {
    int data;
    Node left, right;
 
    Node(int data)
    {
        this.data = data;
        left = right = null;
    }
}
 
class BinaryTree {
    Node root;
 
    // method to print the inorder traversal of
    // the binary tree
    void printInorder(Node node)
    {
        if (node == null)
            return;
 
        /* first recur on left child */
        printInorder(node.left);
 
        /* then print the data of node */
        System.out.print(node.data + " ");
 
        /* now recur on right child */
        printInorder(node.right);
    }
 
    // method to convert the binary tree
    void convertTree(Node root)
    {
        if (root == null)
            return;
 
        int childSum = 0;
 
        // sum of children's data
        if (root.left != null)
            childSum += root.left.data;
        if (root.right != null)
            childSum += root.right.data;
 
        // if children sum is greater than root
        if (childSum >= root.data) {
            root.data = childSum;
        }
        else {
            // if children sum is less than root
            // change both children
            if (root.left != null)
                root.left.data = root.data;
            if (root.right != null)
                root.right.data = root.data;
        }
 
        // now go down the tree and check others - Inorder
        convertTree(root.left);
        convertTree(root.right);
 
        // here is the backtracking part happens, as changes
        // may happen
        int totVal = 0;
 
        if (root.left != null)
            totVal += root.left.data;
        if (root.right != null)
            totVal += root.right.data;
 
        // Leaf node dont update, as it will make it 0
        if (root.left != null || root.right != null)
            root.data = totVal;
        // So that at last the children Sum property stays
        // TRUE
    }
 
    /* Driver code */
    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);
    }
}
 
// This code is contributed by lokeshpotta20.


Python3




#Python code for the above approach
class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None
 
def printInorder(node):
    if node is None:
        return
    # first recur on left child
    printInorder(node.left)
    # then print the data of node
    print(node.data, end=" ")
    # now recur on right child
    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:
        # change root
        root.data = childSum
    else:
        # change both children
        if root.left:
            root.left.data = root.data
        if root.right:
            root.right.data = root.data
    # now go down the tree and check others - Inorder
    convertTree(root.left)
    convertTree(root.right)
    # here is the backtracking part happens, as changes may happen
    totVal = 0
    if root.left:
        totVal += root.left.data
    if root.right:
        totVal += root.right.data
    # Leaf node dont update, as it will make it 0
    if root.left or root.right:
        root.data = totVal
    # So that at last the children Sum property stays TRUE
 
# Driver code
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#




// C# program to convert an arbitrary
// binary tree to a tree that holds
// children sum property
using System;
  
// A binary tree node
public class node{
    public int data;
    public node left, right;
  
    public node(int item){
        data = item;
        left = right = null;
    }
}
  
class GFG{
    public node root;
  
    /* This function changes a tree to
    hold children sum property */
    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){
            // change root
            root.data = childSum;
        }else{
            // change both children
            if(root.left != null) root.left.data = root.data;
            if(root.right != null) root.right.data = root.data;
        }
         
        // now go down the tree and check others - Inorder
        convertTree(root.left);
        convertTree(root.right);
         
        // here is the backtracking part happens, as changes may happend
        int totVal = 0;
         
        if(root.left != null) totVal += root.left.data;
        if(root.right != null) totVal += root.right.data;
         
        // Leaf node don't update, as it will make it 0
        if(root.left != null || root.right != null) root.data = totVal;
        // so that at last the children sum property syas true
    }
  
    public virtual void printInorder(node node){
        if (node == null) return;
      
        /* first recur on left child */
        printInorder(node.left);
      
        /* then print the data of node */
        Console.Write(node.data + " ");
      
        /* now recur on right child */
        printInorder(node.right);
    }
  
    // Driver Code
    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);
    }
}
// THIS CODE IS CONTRIBUTED BY KIRTI AGARWAL(KIRTIAGARWAL23121999)


Javascript




// JavaScript program for the above approach
class node{
    constructor(data){
        this.data = data;
        this.left = null;
        this.right = null;
    }
}
 
// function to print inorder traversal of binary tree
function printInorder(node)
{
    if(node == null) return;
     
    // first recur on left child
    printInorder(node.left);
     
    // then print the data of node
    console.log(node.data + " ");
     
    // now recur on right child
    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){
        // change root
        root.data = childSum;
    }else{
        // change both children
        if(root.left) root.left.data = root.data;
        if(root.right) root.right.data = root.data;
    }
     
    // now go down the tree and check others - Inorder
    convertTree(root.left);
    convertTree(root.right);
     
    // here is the backtracking part happens, as changes may happen
    let totVal = 0;
     
    if(root.left) totVal += root.left.data;
    if(root.right)  totVal += root.right.data;
     
    // Leaf node dont update, as it will make it 0
    if(root.left || root.right) root.data = totVal;
    //So that at last the children Sum property stays TRUE
}
 
// driver code to test above function
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);
 
// THIS CODE IS CONTRIBUTED BY YASH AGARWAL(YASHAGARWAL2852002)


Output

Inorder 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();
    }
}


Python3




from queue import Queue
 
class Node:
    def __init__(self, data):
        self.data = data
        self.left = None
        self.right = None
 
def convert_tree(root):
    # Base case: If the tree is empty or has only one node, return.
    if root is None or (root.left is None and root.right is None):
        return
 
    q = Queue()
    q.put(root)
 
    while not q.empty():
        current = q.get()
 
        # Initialize variables to store the data of the left and right children.
        left_data, right_data = 0, 0
 
        # Check if the left child exists and update left_data.
        if current.left is not None:
            q.put(current.left)
            left_data = current.left.data
 
        # Check if the right child exists and update right_data.
        if current.right is not None:
            q.put(current.right)
            right_data = current.right.data
 
        # Calculate the difference between the sum of left and right children's data and the current node's data.
        diff = left_data + right_data - current.data
 
        # If the difference is positive, add it to the current node's data.
        if diff > 0:
            current.data += diff
 
        # If the difference is negative, distribute it to the left and/or right children.
        if diff < 0:
            # If the left child exists, add the negative difference to it.
            if current.left is not None:
                current.left.data += -diff
            # If the left child doesn't exist, add the negative difference to the right child.
            elif current.right is not None:
                current.right.data += -diff
 
def print_inorder(root):
    if root is None:
        return
 
    # Inorder traversal of the tree (left-root-right).
    print_inorder(root.left)
    print(root.data, end=' ')
    print_inorder(root.right)
 
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: ", end='')
    print_inorder(root)
    print()
 
    convert_tree(root)
 
    print("Inorder traversal after conversion: ", end='')
    print_inorder(root)
    print()  # Add this line to ensure the final output is displayed


C#




using System;
using System.Collections.Generic;
 
class Node
{
    public int Data { get; set; }
    public Node Left { get; set; }
    public Node Right { get; set; }
 
    public Node(int data)
    {
        Data = data;
        Left = null;
        Right = null;
    }
}
 
class Program
{
    // Function to convert the tree as per the given logic
    static void ConvertTree(Node root)
    {
        // If the root is null or a leaf node, no conversion is needed
        if (root == null || (root.Left == null && root.Right == null))
            return;
 
        // Use a queue for level order traversal
        Queue<Node> q = new Queue<Node>();
        q.Enqueue(root);
 
        // Level order traversal to process each node
        while (q.Count > 0)
        {
            Node current = q.Dequeue();
 
            int leftData = 0, rightData = 0;
 
            // Enqueue left child if it exists and update leftData
            if (current.Left != null)
            {
                q.Enqueue(current.Left);
                leftData = current.Left.Data;
            }
 
            // Enqueue right child if it exists and update rightData
            if (current.Right != null)
            {
                q.Enqueue(current.Right);
                rightData = current.Right.Data;
            }
 
            // Calculate the difference between the sum of left and
            // right children and the current node's data
            int diff = leftData + rightData - current.Data;
 
            // If the difference is positive, update the current node's data
            if (diff > 0)
                current.Data += diff;
 
            // If the difference is negative, distribute it to left or right child
            if (diff < 0)
            {
                if (current.Left != null)
                    current.Left.Data += -diff;
                else if (current.Right != null)
                    current.Right.Data += -diff;
            }
        }
    }
 
    // Function to print the inorder traversal of the tree
    static void PrintInorder(Node root)
    {
        if (root == null)
            return;
 
        PrintInorder(root.Left);
        Console.Write(root.Data + " ");
        PrintInorder(root.Right);
    }
 
    static void Main()
    {
        // Sample tree creation
        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);
 
        Console.Write("Inorder traversal before conversion: ");
        PrintInorder(root);
        Console.WriteLine();
 
        // Convert the tree
        ConvertTree(root);
 
        Console.Write("Inorder traversal after conversion: ");
        PrintInorder(root);
        Console.WriteLine();
    }
}


Javascript




// JavaScript Code for the above approach
class Node {
  constructor(data) {
    this.data = data;
    this.left = null;
    this.right = null;
  }
}
 
// Function to modify the binary tree to satisfy the children sum property
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;
 
    // Calculate the sum of left and right child node data, if they exist
    if (current.left !== null) {
      queue.push(current.left);
      leftData = current.left.data;
    }
 
    if (current.right !== null) {
      queue.push(current.right);
      rightData = current.right.data;
    }
 
    // Calculate the difference between the sum of children and current node data
    const diff = leftData + rightData - current.data;
 
    // Update the current node data to satisfy the children sum property
    if (diff > 0)
      current.data += diff;
 
    // If the current node data is greater than the sum of its children,
    // propagate the difference to its children
    if (diff < 0) {
      if (current.left !== null)
        current.left.data += -diff;
      else if (current.right !== null)
        current.right.data += -diff;
    }
  }
}
 
// Function to print the inorder traversal of the binary tree
function printInorder(root) {
  if (root === null)
    return;
 
  printInorder(root.left);
  process.stdout.write(root.data + " ");
  printInorder(root.right);
}
 
// Create the binary tree
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();
 
// Modify the binary tree to satisfy the children sum property
convertTree(root);
 
console.log("Inorder traversal after conversion:");
printInorder(root);
console.log();
// THIS CODE IS CONTRIBUTED BY KIRTI AGARWAL


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).



Last Updated : 12 Nov, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads