Given a root binary tree, you need to find the maximum value which you can get by subtracting the value of node B from the value of node A, where A and B are two nodes of the binary tree and A is an ancestor of B.
Examples:
Input: root = [5, 2, 1]
Output: 4 Explanation: The maximum difference we can get is 4, which is between 5 and 1.
Input: root = [1, 2, 3, N, N, N, 7]
Output: -1 Explanation: The maximum difference we can get is -1, which is between 1 and 2.
[Naive Approach] DFS for Every Ancestor - O(n^2) Time and O(h) Space
The idea is to consider every node as an ancestor and traverse all nodes in its subtree. For every ancestor-descendant pair, compute their difference and update the maximum answer.
Working of Approach:
Traverse every node and treat it as the ancestor.
Perform DFS on its left and right subtrees.
For every descendant, calculate ancestor->data - descendant->data.
Keep updating the maximum difference.
Return the maximum value obtained.
C++
#include<climits>#include<iostream>#include<queue>#include<sstream>#include<vector>usingnamespacestd;classNode{public:intdata;Node*left;Node*right;Node(intval){data=val;left=right=nullptr;}};// DFS to check all descendants of an ancestorvoidfindDiff(Node*ancestor,Node*curr,int&ans){if(curr==nullptr)return;// Update maximum differenceans=max(ans,ancestor->data-curr->data);findDiff(ancestor,curr->left,ans);findDiff(ancestor,curr->right,ans);}// Treat every node as ancestorvoidtraverse(Node*root,int&ans){if(root==nullptr)return;findDiff(root,root->left,ans);findDiff(root,root->right,ans);traverse(root->left,ans);traverse(root->right,ans);}intmaxDiff(Node*root){intans=INT_MIN;traverse(root,ans);returnans;}// Function to build tree from level order inputNode*buildTree(stringstr){if(str.size()==0||str[0]=='N')returnnullptr;vector<string>ip;stringstreamss(str);stringtemp;while(ss>>temp)ip.push_back(temp);Node*root=newNode(stoi(ip[0]));queue<Node*>q;q.push(root);inti=1;while(!q.empty()&&i<ip.size()){Node*curr=q.front();q.pop();if(ip[i]!="N"){curr->left=newNode(stoi(ip[i]));q.push(curr->left);}i++;if(i>=ip.size())break;if(ip[i]!="N"){curr->right=newNode(stoi(ip[i]));q.push(curr->right);}i++;}returnroot;}intmain(){// Construct the following binary tree// 5// / \ // 2 1Node*root=newNode(5);root->left=newNode(2);root->right=newNode(1);cout<<maxDiff(root);return0;}
Java
importjava.util.*;// Structure of a Binary Tree NodeclassNode{intdata;Nodeleft,right;Node(intval){data=val;left=right=null;}}publicclassGFG{// DFS to check all descendants of an ancestorstaticvoidfindDiff(Nodeancestor,Nodecurr,int[]ans){if(curr==null)return;// Update maximum differenceans[0]=Math.max(ans[0],ancestor.data-curr.data);findDiff(ancestor,curr.left,ans);findDiff(ancestor,curr.right,ans);}// Treat every node as ancestorstaticvoidtraverse(Noderoot,int[]ans){if(root==null)return;findDiff(root,root.left,ans);findDiff(root,root.right,ans);traverse(root.left,ans);traverse(root.right,ans);}staticintmaxDiff(Noderoot){int[]ans={Integer.MIN_VALUE};traverse(root,ans);returnans[0];}// Construct binary tree from level order inputstaticNodebuildTree(Stringstr){if(str.length()==0||str.charAt(0)=='N')returnnull;String[]ip=str.split("\\s+");Noderoot=newNode(Integer.parseInt(ip[0]));Queue<Node>q=newLinkedList<>();q.offer(root);inti=1;while(!q.isEmpty()&&i<ip.length){Nodecurr=q.poll();if(!ip[i].equals("N")){curr.left=newNode(Integer.parseInt(ip[i]));q.offer(curr.left);}i++;if(i>=ip.length)break;if(!ip[i].equals("N")){curr.right=newNode(Integer.parseInt(ip[i]));q.offer(curr.right);}i++;}returnroot;}publicstaticvoidmain(String[]args){// Construct the following binary tree// 5// / \// 2 1Noderoot=newNode(5);root.left=newNode(2);root.right=newNode(1);System.out.println(maxDiff(root));}}
Python
classNode:def__init__(self,data):self.data=dataself.left=Noneself.right=None# DFS to check all descendants of an ancestordeffindDiff(ancestor,curr,ans):ifcurrisNone:return# Update maximum differenceans[0]=max(ans[0],ancestor.data-curr.data)findDiff(ancestor,curr.left,ans)findDiff(ancestor,curr.right,ans)# Treat every node as ancestordeftraverse(root,ans):ifrootisNone:returnfindDiff(root,root.left,ans)findDiff(root,root.right,ans)traverse(root.left,ans)traverse(root.right,ans)defmaxDiff(root):ans=[float('-inf')]traverse(root,ans)returnans[0]# Function to build tree from level order inputdefbuildTree(s):ifnotsors[0]=='N':returnNoneip=s.split()root=Node(int(ip[0]))queue=[root]i=1whilequeueandi<len(ip):curr=queue.pop(0)ifip[i]!='N':curr.left=Node(int(ip[i]))queue.append(curr.left)i+=1ifi>=len(ip):breakifip[i]!='N':curr.right=Node(int(ip[i]))queue.append(curr.right)i+=1returnroot# Driver Codeif__name__=='__main__':root=buildTree('5 2 1')print(maxDiff(root))
C#
usingSystem;usingSystem.Collections.Generic;// Structure of a Binary Tree NodeclassNode{publicintdata;publicNodeleft,right;publicNode(intval){data=val;left=right=null;}}classGFG{// DFS to check all descendants of an ancestorstaticvoidFindDiff(Nodeancestor,Nodecurr,refintans){if(curr==null)return;// Update maximum differenceans=Math.Max(ans,ancestor.data-curr.data);FindDiff(ancestor,curr.left,refans);FindDiff(ancestor,curr.right,refans);}// Treat every node as ancestorstaticvoidTraverse(Noderoot,refintans){if(root==null)return;FindDiff(root,root.left,refans);FindDiff(root,root.right,refans);Traverse(root.left,refans);Traverse(root.right,refans);}staticintmaxDiff(Noderoot){intans=int.MinValue;Traverse(root,refans);returnans;}// Construct binary tree from level order inputstaticNodeBuildTree(stringstr){if(string.IsNullOrEmpty(str)||str[0]=='N')returnnull;string[]ip=str.Split();Noderoot=newNode(int.Parse(ip[0]));Queue<Node>q=newQueue<Node>();q.Enqueue(root);inti=1;while(q.Count>0&&i<ip.Length){Nodecurr=q.Dequeue();if(ip[i]!="N"){curr.left=newNode(int.Parse(ip[i]));q.Enqueue(curr.left);}i++;if(i>=ip.Length)break;if(ip[i]!="N"){curr.right=newNode(int.Parse(ip[i]));q.Enqueue(curr.right);}i++;}returnroot;}staticvoidMain(){// Construct the following binary tree// 5// / \// 2 1Noderoot=newNode(5);root.left=newNode(2);root.right=newNode(1);Console.WriteLine(maxDiff(root));}}
JavaScript
// Node structurefunctionNode(val){this.data=val;this.left=null;this.right=null;}// DFS to check all descendants of an ancestorfunctionfindDiff(ancestor,curr,ans){if(curr===null)return;// Update maximum differenceans.value=Math.max(ans.value,ancestor.data-curr.data);findDiff(ancestor,curr.left,ans);findDiff(ancestor,curr.right,ans);}// Treat every node as ancestorfunctiontraverse(root,ans){if(root===null)return;findDiff(root,root.left,ans);findDiff(root,root.right,ans);traverse(root.left,ans);traverse(root.right,ans);}functionmaxDiff(root){letans={value:Number.MIN_SAFE_INTEGER};traverse(root,ans);returnans.value;}// Function to build tree from level order inputfunctionbuildTree(str){if(str.length===0||str[0]==="N")returnnull;letip=str.trim().split(/\s+/);letroot=newNode(parseInt(ip[0]));letq=[];q.push(root);leti=1;while(q.length>0&&i<ip.length){letcurr=q.shift();if(ip[i]!=="N"){curr.left=newNode(parseInt(ip[i]));q.push(curr.left);}i++;if(i>=ip.length)break;if(ip[i]!=="N"){curr.right=newNode(parseInt(ip[i]));q.push(curr.right);}i++;}returnroot;}// Driver Code// Construct the following binary tree// 5// / \// 2 1letroot=newNode(5);root.left=newNode(2);root.right=newNode(1);console.log(maxDiff(root));
Output
4
[Expected Approach] Postorder Traversal with Minimum Subtree Value - O(n) Time and O(h) Space
The idea is to traverse the tree in postorder and return the minimum value present in every subtree. This minimum descendant value is used to compute the maximum difference for the current ancestor.
Working of Approach:
Traverse the tree using postorder recursion.
Return the minimum value from the left and right subtrees.
Update the answer using current node - minimum descendant.
Return the minimum value in the current subtree.
The final answer is the maximum difference found.
Let us understand with an example: Input: root = [5, 2, 1]
The leaf nodes 2 and 1 return their values as the minimum values of their respective subtrees.
For node 5, the minimum value among its descendants is 1.
The difference 5 - 1 = 4 is calculated and the answer is updated.
The minimum value in the subtree rooted at 5 remains 1.
Therefore, the maximum difference between an ancestor and its descendant is 4.
C++
#include<climits>#include<iostream>#include<queue>#include<sstream>#include<vector>usingnamespacestd;classNode{public:intdata;Node*left;Node*right;Node(intval){data=val;left=right=nullptr;}};intmaxDiffUtil(Node*t,int*res){// returning Maximum int value if node is null.if(t==nullptr)returnINT_MAX;// if there are no child nodes then we just return data at current node.if(t->left==nullptr&&t->right==nullptr)returnt->data;// recursively calling for left and right subtrees and// choosing their minimum.intval=min(maxDiffUtil(t->left,res),maxDiffUtil(t->right,res));// updating res if (node value - min value from subtrees) is bigger than res.*res=max(*res,t->data-val);// returning minimum value got so far.returnmin(val,t->data);}// Function to return the maximum difference between any node and its ancestor.intmaxDiff(Node*root){intres=INT_MIN;maxDiffUtil(root,&res);// returning the result.returnres;}// Function to build tree from level order inputNode*buildTree(stringstr){if(str.size()==0||str[0]=='N')returnnullptr;vector<string>ip;stringstreamss(str);stringtemp;while(ss>>temp)ip.push_back(temp);Node*root=newNode(stoi(ip[0]));queue<Node*>q;q.push(root);inti=1;while(!q.empty()&&i<ip.size()){Node*curr=q.front();q.pop();if(ip[i]!="N"){curr->left=newNode(stoi(ip[i]));q.push(curr->left);}i++;if(i>=ip.size())break;if(ip[i]!="N"){curr->right=newNode(stoi(ip[i]));q.push(curr->right);}i++;}returnroot;}intmain(){// Construct the following binary tree// 5// / \ // 2 1Node*root=newNode(5);root->left=newNode(2);root->right=newNode(1);cout<<maxDiff(root);return0;}
Java
importjava.util.*;// Structure of a Binary Tree NodeclassNode{intdata;Nodeleft,right;Node(intval){data=val;left=right=null;}}publicclassGFG{staticintmaxDiffUtil(Nodet,int[]res){// Returning maximum value if node is nullif(t==null)returnInteger.MAX_VALUE;// Leaf nodeif(t.left==null&&t.right==null)returnt.data;// Recursively find minimum from left and right// subtreesintval=Math.min(maxDiffUtil(t.left,res),maxDiffUtil(t.right,res));// Update answerres[0]=Math.max(res[0],t.data-val);// Return minimum value so farreturnMath.min(val,t.data);}// Function to return the maximum differencestaticintmaxDiff(Noderoot){int[]res={Integer.MIN_VALUE};maxDiffUtil(root,res);returnres[0];}// Function to build tree from level order inputstaticNodebuildTree(Stringstr){if(str.length()==0||str.charAt(0)=='N')returnnull;String[]ip=str.split("\\s+");Noderoot=newNode(Integer.parseInt(ip[0]));Queue<Node>q=newLinkedList<>();q.offer(root);inti=1;while(!q.isEmpty()&&i<ip.length){Nodecurr=q.poll();if(!ip[i].equals("N")){curr.left=newNode(Integer.parseInt(ip[i]));q.offer(curr.left);}i++;if(i>=ip.length)break;if(!ip[i].equals("N")){curr.right=newNode(Integer.parseInt(ip[i]));q.offer(curr.right);}i++;}returnroot;}publicstaticvoidmain(String[]args){// Construct the following binary tree// 5// / \// 2 1Noderoot=newNode(5);root.left=newNode(2);root.right=newNode(1);System.out.println(maxDiff(root));}}
Python
fromqueueimportQueueclassNode:def__init__(self,data):self.data=dataself.left=Noneself.right=NonedefmaxDiffUtil(t,res):# returning Maximum int value if node is null.iftisNone:returnfloat('inf')# if there are no child nodes then we just return data at current node.ift.leftisNoneandt.rightisNone:returnt.data# recursively calling for left and right subtrees and# choosing their minimum.val=min(maxDiffUtil(t.left,res),maxDiffUtil(t.right,res))# updating res if (node value - min value from subtrees) is bigger than res.res[0]=max(res[0],t.data-val)# returning minimum value got so far.returnmin(val,t.data)# Function to return the maximum difference between any node and its ancestor.defmaxDiff(root):res=[float('-inf')]maxDiffUtil(root,res)# returning the result.returnres[0]# Function to build tree from level order inputdefbuildTree(str):ifstr==""orstr[0]=='N':returnNoneip=str.split()root=Node(int(ip[0]))q=Queue()q.put(root)i=1whilenotq.empty()andi<len(ip):curr=q.get()ifip[i]!='N':curr.left=Node(int(ip[i]))q.put(curr.left)i+=1ifi>=len(ip):breakifip[i]!='N':curr.right=Node(int(ip[i]))q.put(curr.right)i+=1returnrootif__name__=='__main__':# Construct the following binary tree# 5# / \# 2 1root=Node(5)root.left=Node(2)root.right=Node(1)print(maxDiff(root))
C#
usingSystem;usingSystem.Collections.Generic;// Structure of a Binary Tree NodeclassNode{publicintdata;publicNodeleft,right;publicNode(intval){data=val;left=right=null;}}classGFG{staticintMaxDiffUtil(Nodet,refintres){// Returning maximum value if node is nullif(t==null)returnint.MaxValue;// Leaf nodeif(t.left==null&&t.right==null)returnt.data;// Recursively find minimum from left and right// subtreesintval=Math.Min(MaxDiffUtil(t.left,refres),MaxDiffUtil(t.right,refres));// Update answerres=Math.Max(res,t.data-val);// Return minimum value so farreturnMath.Min(val,t.data);}// Function to return the maximum differencestaticintmaxDiff(Noderoot){intres=int.MinValue;MaxDiffUtil(root,refres);returnres;}// Function to build tree from level order inputstaticNodeBuildTree(stringstr){if(string.IsNullOrEmpty(str)||str[0]=='N')returnnull;string[]ip=str.Split();Noderoot=newNode(int.Parse(ip[0]));Queue<Node>q=newQueue<Node>();q.Enqueue(root);inti=1;while(q.Count>0&&i<ip.Length){Nodecurr=q.Dequeue();if(ip[i]!="N"){curr.left=newNode(int.Parse(ip[i]));q.Enqueue(curr.left);}i++;if(i>=ip.Length)break;if(ip[i]!="N"){curr.right=newNode(int.Parse(ip[i]));q.Enqueue(curr.right);}i++;}returnroot;}staticvoidMain(){// Construct the following binary tree// 5// / \// 2 1Noderoot=newNode(5);root.left=newNode(2);root.right=newNode(1);Console.WriteLine(maxDiff(root));}}
JavaScript
// Node structurefunctionNode(val){this.data=val;this.left=null;this.right=null;}functionmaxDiffUtil(t,res){// Returning maximum value if node is nullif(t===null)returnNumber.MAX_SAFE_INTEGER;// Leaf nodeif(t.left===null&&t.right===null)returnt.data;// Recursively find minimum from left and right subtreesletval=Math.min(maxDiffUtil(t.left,res),maxDiffUtil(t.right,res));// Update answerres.value=Math.max(res.value,t.data-val);// Return minimum value so farreturnMath.min(val,t.data);}// Function to return the maximum differencefunctionmaxDiff(root){letres={value:Number.MIN_SAFE_INTEGER};maxDiffUtil(root,res);returnres.value;}// Function to build tree from level order inputfunctionbuildTree(str){if(str.length===0||str[0]==="N")returnnull;letip=str.trim().split(/\s+/);letroot=newNode(parseInt(ip[0]));letq=[];q.push(root);leti=1;while(q.length>0&&i<ip.length){letcurr=q.shift();if(ip[i]!=="N"){curr.left=newNode(parseInt(ip[i]));q.push(curr.left);}i++;if(i>=ip.length)break;if(ip[i]!=="N"){curr.right=newNode(parseInt(ip[i]));q.push(curr.right);}i++;}returnroot;}// Driver Code// Construct the following binary tree// 5// / \// 2 1letroot=newNode(5);root.left=newNode(2);root.right=newNode(1);console.log(maxDiff(root));