Given the root of a binary tree with integer values, Find the maximum sum of node values such that no two nodes connected by an edge are both included in the sum.
Examples:
Input:
Output: 11 Explanation: The maximum sum is sum of node 11.
Input:
Output: 27 Explanation: The maximum sum is sum of nodes 15, and 12, i.e., 27. These nodes are non adjacent.
We can solve this problem by considering the fact that both node and its immediate children can’t be in sum at the same time.
Include the current node's value in the sum: In this case, we cannot include the values of its immediate children in the sum. Therefore, we recursively call the function on the grandchildren of the current node.
Exclude the current node's value in the sum: In this case, we are allowed to include the values of its immediate children in the sum. So, we recursively call the function on the immediate children of the current node.
Finally we will choose maximum from both of the results.
C++
#include<iostream>#include<algorithm>usingnamespacestd;// Node StructureclassNode{public:intdata;Node*left;Node*right;Node(intx){data=x;left=right=NULL;}};// method to return the maximum // sum rooted at the node 'node'intgetMaxSumUtil(Node*node){if(node==NULL)return0;intincludeNode=node->data;if(node->left!=NULL){includeNode+=getMaxSumUtil(node->left->left)+getMaxSumUtil(node->left->right);}if(node->right!=NULL){includeNode+=getMaxSumUtil(node->right->left)+getMaxSumUtil(node->right->right);}intexcludeNode=getMaxSumUtil(node->left)+getMaxSumUtil(node->right);// The result for the current node is the// maximum of including or excluding itreturnmax(includeNode,excludeNode);}intgetMaxSum(Node*root){if(root==NULL)return0;returngetMaxSumUtil(root);}intmain(){// Create binary tree// 1// / \ // 2 3// / / \ // 1 4 5Node*root=newNode(1);root->left=newNode(2);root->right=newNode(3);root->right->left=newNode(4);root->right->right=newNode(5);root->left->left=newNode(1);cout<<getMaxSum(root)<<endl;return0;}
Java
// Node StructureclassNode{intdata;Nodeleft,right;Node(intx){data=x;left=right=null;}}classGFG{// method to return the maximum // sum rooted at the node 'node'staticintgetMaxSumUtil(Nodenode){if(node==null)return0;intincludeNode=node.data;if(node.left!=null){includeNode+=getMaxSumUtil(node.left.left)+getMaxSumUtil(node.left.right);}if(node.right!=null){includeNode+=getMaxSumUtil(node.right.left)+getMaxSumUtil(node.right.right);}intexcludeNode=getMaxSumUtil(node.left)+getMaxSumUtil(node.right);// The result for the current node is the// maximum of including or excluding itreturnMath.max(includeNode,excludeNode);}staticintgetMaxSum(Noderoot){if(root==null)return0;returngetMaxSumUtil(root);}publicstaticvoidmain(String[]args){// Create binary tree// 1// / \// 2 3// / / \// 1 4 5Noderoot=newNode(1);root.left=newNode(2);root.right=newNode(3);root.right.left=newNode(4);root.right.right=newNode(5);root.left.left=newNode(1);System.out.println(getMaxSum(root));}}
Python
# Node StructureclassNode:def__init__(self,x):self.data=xself.left=Noneself.right=None# method to return the maximum # sum rooted at the node 'node'defgetMaxSumUtil(node):ifnodeisNone:return0includeNode=node.dataifnode.leftisnotNone:includeNode+=getMaxSumUtil(node.left.left)+ \
getMaxSumUtil(node.left.right)ifnode.rightisnotNone:includeNode+=getMaxSumUtil(node.right.left)+ \
getMaxSumUtil(node.right.right)excludeNode=getMaxSumUtil(node.left)+ \
getMaxSumUtil(node.right)# The result for the current node is the# maximum of including or excluding itreturnmax(includeNode,excludeNode)defgetMaxSum(root):ifrootisNone:return0returngetMaxSumUtil(root)if__name__=="__main__":# Create binary tree# 1# / \# 2 3# / / \# 1 4 5root=Node(1)root.left=Node(2)root.right=Node(3)root.right.left=Node(4)root.right.right=Node(5)root.left.left=Node(1)print(getMaxSum(root))
C#
usingSystem;// Node StructureclassNode{publicintdata;publicNodeleft,right;publicNode(intx){data=x;left=right=null;}}classGFG{// method to return the maximum // sum rooted at the node 'node'staticintgetMaxSumUtil(Nodenode){if(node==null)return0;intincludeNode=node.data;if(node.left!=null){includeNode+=getMaxSumUtil(node.left.left)+getMaxSumUtil(node.left.right);}if(node.right!=null){includeNode+=getMaxSumUtil(node.right.left)+getMaxSumUtil(node.right.right);}intexcludeNode=getMaxSumUtil(node.left)+getMaxSumUtil(node.right);// The result for the current node is// the maximum of including or excluding itreturnMath.Max(includeNode,excludeNode);}staticintgetMaxSum(Noderoot){if(root==null)return0;returngetMaxSumUtil(root);}staticvoidMain(string[]args){// Creating a binary tree with the following structure:// 1// / \// 2 3// / / \// 1 4 5Noderoot=newNode(1);root.left=newNode(2);root.right=newNode(3);root.right.left=newNode(4);root.right.right=newNode(5);root.left.left=newNode(1);Console.WriteLine(getMaxSum(root));}}
JavaScript
// Node StructureclassNode{constructor(x){this.data=x;this.left=null;this.right=null;}}// method to return the maximum // sum rooted at the node 'node'functiongetMaxSumUtil(node){if(node===null)return0;letincludeNode=node.data;if(node.left!==null){includeNode+=getMaxSumUtil(node.left.left)+getMaxSumUtil(node.left.right);}if(node.right!==null){includeNode+=getMaxSumUtil(node.right.left)+getMaxSumUtil(node.right.right);}letexcludeNode=getMaxSumUtil(node.left)+getMaxSumUtil(node.right);// The result for the current node is the// maximum of including or excluding itreturnMath.max(includeNode,excludeNode);}functiongetMaxSum(root){if(root===null)return0;returngetMaxSumUtil(root);}// Driver code// Create binary tree// 1// / \// 2 3// / / \// 1 4 5letroot=newNode(1);root.left=newNode(2);root.right=newNode(3);root.right.left=newNode(4);root.right.right=newNode(5);root.left.left=newNode(1);console.log(getMaxSum(root));
Output
11
Time Complexity: O(2n), Auxiliary Space: O(h), where h is height of binary tree due to recursion stack space
[Expected Approach 1] Using Top-Down DP (Memorization) - O(n) Time and O(n) Space
The naive approach leads to recalculating results for the same nodes multiple times. For example, if we include the root node, we recursively compute the sum for its grandchildren (nodes 4 and 5). But if we exclude the root, we compute the sum for its children, and node 3 also computes the sum for its children (4 and 5 again).
When a node's value is needed again, we directly return it from the map instead of recalculating.
C++
#include<iostream>#include<unordered_map>usingnamespacestd;// Node StructureclassNode{public:intdata;Node*left,*right;Node(intx){data=x;left=right=NULL;}};// method to return the maximum // sum rooted at the node 'node'intgetMaxSumUtil(Node*node,unordered_map<Node*,int>&memo){if(node==NULL)return0;if(memo.find(node)!=memo.end()){returnmemo[node];}// Calculate the maximum sum // including the current nodeintinclude=node->data;if(node->left!=NULL){include+=getMaxSumUtil(node->left->left,memo)+getMaxSumUtil(node->left->right,memo);}if(node->right!=NULL){include+=getMaxSumUtil(node->right->left,memo)+getMaxSumUtil(node->right->right,memo);}// Calculate the maximum sum // excluding the current nodeintexclude=getMaxSumUtil(node->left,memo)+getMaxSumUtil(node->right,memo);memo[node]=max(include,exclude);returnmemo[node];}intgetMaxSum(Node*root){unordered_map<Node*,int>memo;returngetMaxSumUtil(root,memo);}intmain(){// Create binary tree // 1// / \ // 2 3// / / \ // 1 4 5Node*root=newNode(1);root->left=newNode(2);root->right=newNode(3);root->right->left=newNode(4);root->right->right=newNode(5);root->left->left=newNode(1);cout<<getMaxSum(root)<<endl;return0;}
Java
importjava.util.HashMap;// Node StructureclassNode{intdata;Nodeleft,right;Node(intx){data=x;left=right=null;}}classGFG{// method to return the maximum // sum rooted at the node 'node'staticintgetMaxSumUtil(Nodenode,HashMap<Node,Integer>memo){if(node==null)return0;if(memo.containsKey(node)){returnmemo.get(node);}// Calculate the maximum sum // including the current nodeintinclude=node.data;if(node.left!=null){include+=getMaxSumUtil(node.left.left,memo)+getMaxSumUtil(node.left.right,memo);}if(node.right!=null){include+=getMaxSumUtil(node.right.left,memo)+getMaxSumUtil(node.right.right,memo);}// Calculate the maximum sum // excluding the current nodeintexclude=getMaxSumUtil(node.left,memo)+getMaxSumUtil(node.right,memo);memo.put(node,Math.max(include,exclude));returnmemo.get(node);}staticintgetMaxSum(Noderoot){HashMap<Node,Integer>memo=newHashMap<>();returngetMaxSumUtil(root,memo);}publicstaticvoidmain(String[]args){// Create binary tree // 1// / \// 2 3// / / \// 1 4 5Noderoot=newNode(1);root.left=newNode(2);root.right=newNode(3);root.right.left=newNode(4);root.right.right=newNode(5);root.left.left=newNode(1);System.out.println(getMaxSum(root));}}
Python
# Node StructureclassNode:def__init__(self,x):self.data=xself.left=Noneself.right=None# method to return the maximum # sum rooted at the node 'node'defgetMaxSumUtil(node,memo):ifnodeisNone:return0ifnodeinmemo:returnmemo[node]# Calculate the maximum sum # including the current nodeinclude=node.dataifnode.leftisnotNone:include+=getMaxSumUtil(node.left.left,memo)+ \
getMaxSumUtil(node.left.right,memo)ifnode.rightisnotNone:include+=getMaxSumUtil(node.right.left,memo)+ \
getMaxSumUtil(node.right.right,memo)# Calculate the maximum sum # excluding the current nodeexclude=getMaxSumUtil(node.left,memo)+getMaxSumUtil(node.right,memo)memo[node]=max(include,exclude)returnmemo[node]defgetMaxSum(root):memo={}returngetMaxSumUtil(root,memo)if__name__=="__main__":# Create binary tree # 1# / \# 2 3# / / \# 1 4 5root=Node(1)root.left=Node(2)root.right=Node(3)root.right.left=Node(4)root.right.right=Node(5)root.left.left=Node(1)print(getMaxSum(root))
C#
usingSystem;usingSystem.Collections.Generic;// Node StructureclassNode{publicintdata;publicNodeleft,right;publicNode(intx){data=x;left=right=null;}}classGFG{// method to return the maximum // sum rooted at the node 'node'staticintgetMaxSumUtil(Nodenode,Dictionary<Node,int>memo){if(node==null)return0;if(memo.ContainsKey(node)){returnmemo[node];}// Calculate the maximum sum // including the current nodeintinclude=node.data;if(node.left!=null){include+=getMaxSumUtil(node.left.left,memo)+getMaxSumUtil(node.left.right,memo);}if(node.right!=null){include+=getMaxSumUtil(node.right.left,memo)+getMaxSumUtil(node.right.right,memo);}// Calculate the maximum sum // excluding the current nodeintexclude=getMaxSumUtil(node.left,memo)+getMaxSumUtil(node.right,memo);memo[node]=Math.Max(include,exclude);returnmemo[node];}staticintgetMaxSum(Noderoot){Dictionary<Node,int>memo=newDictionary<Node,int>();returngetMaxSumUtil(root,memo);}staticvoidMain(string[]args){// Create binary tree // 1// / \// 2 3// / / \// 1 4 5Noderoot=newNode(1);root.left=newNode(2);root.right=newNode(3);root.right.left=newNode(4);root.right.right=newNode(5);root.left.left=newNode(1);Console.WriteLine(getMaxSum(root));}}
JavaScript
// Node StructureclassNode{constructor(x){this.data=x;this.left=null;this.right=null;}}// method to return the maximum // sum rooted at the node 'node'functiongetMaxSumUtil(node,memo){if(node===null)return0;if(memo.has(node)){returnmemo.get(node);}// Calculate the maximum sum // including the current nodeletinclude=node.data;if(node.left!==null){include+=getMaxSumUtil(node.left.left,memo)+getMaxSumUtil(node.left.right,memo);}if(node.right!==null){include+=getMaxSumUtil(node.right.left,memo)+getMaxSumUtil(node.right.right,memo);}// Calculate the maximum sum // excluding the current nodeletexclude=getMaxSumUtil(node.left,memo)+getMaxSumUtil(node.right,memo);memo.set(node,Math.max(include,exclude));returnmemo.get(node);}functiongetMaxSum(root){letmemo=newMap();returngetMaxSumUtil(root,memo);}// Create binary tree // 1// / \// 2 3// / / \// 1 4 5letroot=newNode(1);root.left=newNode(2);root.right=newNode(3);root.right.left=newNode(4);root.right.right=newNode(5);root.left.left=newNode(1);console.log(getMaxSum(root));
Output
11
[Expected Approach 2] Using Include-Exclude Strategy
In this approach, we return a list for each node in the binary tree such that the first of the pair indicates the maximum sum when the data of a node is included and the second indicates the maximum sum when the data of a particular node is not included.
C++
#include<iostream>#include<vector>usingnamespacestd;// Node StructureclassNode{public:intdata;Node*left;Node*right;Node(intx){data=x;left=right=NULL;}};vector<int>maxSumHelper(Node*root){if(root==NULL)return{0,0};vector<int>resLeft=maxSumHelper(root->left);vector<int>resRight=maxSumHelper(root->right);intinclude=root->data+resLeft[1]+resRight[1];intexclude=max(resLeft[0],resLeft[1])+max(resRight[0],resRight[1]);// returns a vector having 2 values// 1st value being max sum when root node is included// 2nd value being max sum when root node is excludedreturn{include,exclude};}intgetMaxSum(Node*root){vector<int>res=maxSumHelper(root);returnmax(res[0],res[1]);}intmain(){// Create binary tree// 1// / \ // 2 3// / / \ // 1 4 5Node*root=newNode(1);root->left=newNode(2);root->right=newNode(3);root->right->left=newNode(4);root->right->right=newNode(5);root->left->left=newNode(1);cout<<getMaxSum(root)<<endl;return0;}
Java
importjava.util.ArrayList;importjava.util.Arrays;// Node StructureclassNode{intdata;Nodeleft,right;Node(intdata){this.data=data;left=right=null;}};classGFG{staticArrayList<Integer>maxSumHelper(Noderoot){if(root==null){returnnewArrayList(Arrays.asList(0,0));}ArrayList<Integer>resLeft=maxSumHelper(root.left);ArrayList<Integer>resRight=maxSumHelper(root.right);intinclude=root.data+resLeft.get(1)+resRight.get(1);intexclude=Math.max(resLeft.get(1),resLeft.get(0))+Math.max(resRight.get(1),resRight.get(0));// returns a vector having 2 values// 1st value being max sum when root node is included// 2nd value being max sum when root node is excludedreturnnewArrayList<>(Arrays.asList(include,exclude));}staticintgetMaxSum(Noderoot){ArrayList<Integer>res=maxSumHelper(root);returnMath.max(res.get(0),res.get(1));}publicstaticvoidmain(Stringargs[]){// Creating a binary tree// 1// / \// 2 3// / / \// 1 4 5Noderoot=newNode(1);root.left=newNode(2);root.right=newNode(3);root.right.left=newNode(4);root.right.right=newNode(5);root.left.left=newNode(1);System.out.print(getMaxSum(root));}}
Python
# Node StructureclassNode:def__init__(self,x):self.data=xself.left=Noneself.right=NonedefmaxSumHelper(root):ifrootisNone:return[0,0]resLeft=maxSumHelper(root.left)resRight=maxSumHelper(root.right)include=root.data+resLeft[1]+resRight[1]exclude=max(resLeft[0],resLeft[1])+ \
max(resRight[0],resRight[1])# returns a vector having 2 values# 1st value being max sum when root node is included# 2nd value being max sum when root node is excludedreturn[include,exclude]defgetMaxSum(root):res=maxSumHelper(root)returnmax(res[0],res[1])if__name__=="__main__":# Create binary tree# 1# / \# 2 3# / / \# 1 4 5root=Node(1)root.left=Node(2)root.right=Node(3)root.right.left=Node(4)root.right.right=Node(5)root.left.left=Node(1)print(getMaxSum(root))
C#
usingSystem;usingSystem.Collections.Generic;// Node StructureclassNode{publicintdata;publicNodeleft,right;publicNode(intx){data=x;left=right=null;}}classGFG{staticList<int>maxSumHelper(Noderoot){if(root==null)returnnewList<int>{0,0};List<int>resLeft=maxSumHelper(root.left);List<int>resRight=maxSumHelper(root.right);intinclude=root.data+resLeft[1]+resRight[1];intexclude=Math.Max(resLeft[0],resLeft[1])+Math.Max(resRight[0],resRight[1]);// returns a vector having 2 values// 1st value being max sum when root node is included// 2nd value being max sum when root node is excludedreturnnewList<int>{include,exclude};}staticintgetMaxSum(Noderoot){List<int>res=maxSumHelper(root);returnMath.Max(res[0],res[1]);}staticvoidMain(string[]args){// Create binary tree// 1// / \// 2 3// / / \// 1 4 5Noderoot=newNode(1);root.left=newNode(2);root.right=newNode(3);root.right.left=newNode(4);root.right.right=newNode(5);root.left.left=newNode(1);Console.WriteLine(getMaxSum(root));}}
JavaScript
// Node StructureclassNode{constructor(x){this.data=x;this.left=null;this.right=null;}}functionmaxSumHelper(root){if(root===null){return[0,0];}letresLeft=maxSumHelper(root.left);letresRight=maxSumHelper(root.right);letinclude=root.data+resLeft[1]+resRight[1];letexclude=Math.max(resLeft[0],resLeft[1])+Math.max(resRight[0],resRight[1]);// returns a vector having 2 values// 1st value being max sum when root node is included// 2nd value being max sum when root node is excludedreturn[include,exclude];}functiongetMaxSum(root){letres=maxSumHelper(root);returnMath.max(res[0],res[1]);}// Driver code// Create binary tree// 1// / \// 2 3// / / \// 1 4 5letroot=newNode(1);root.left=newNode(2);root.right=newNode(3);root.right.left=newNode(4);root.right.right=newNode(5);root.left.left=newNode(1);console.log(getMaxSum(root));
Output
11
Time Complexity: O(n) Auxiliary Space: O(h), where h is height of binary tree due to recursion stack space