[Approach] Recursive Binary Tree Reconstruction - O(n2) Time and O(n) Space
The main idea is that a general binary tree cannot always be uniquely constructed from preorder and postorder traversals alone, because multiple trees may produce the same pair of traversals. Still, we can reconstruct one valid tree by using the relationship between the traversal orders.
The first element in preorder is always the root of the current subtree.
The next element in preorder represents the left child, whose position in postorder helps determine the extent of the left subtree.
All nodes in postorder up to that position form the left subtree, and the remaining nodes (excluding the root) form the right subtree.
We then recursively construct the left and right subtrees using their respective preorder and postorder segments and attach them to the root.
C++
#include<iostream>#include<vector>#include<queue>usingnamespacestd;// Node StructureclassNode{public:intdata;Node*left;Node*right;Node(intx){data=x;left=right=nullptr;}};// Recursive function to construct binary// tree from preorder and postorderNode*constructTreeUtil(vector<int>&pre,vector<int>&post,int&preIndex,intl,inth,intsize){if(preIndex>=size||l>h)returnnullptr;// Create root node from current preorder elementNode*root=newNode(pre[preIndex++]);// If there is only one element, return it as leaf nodeif(l==h)returnroot;// Find the next preorder element in postorder// to split left and right subtreesinti;for(i=l;i<=h;++i)if(pre[preIndex]==post[i])break;if(i<=h){// Recursively construct left and right subtreesroot->left=constructTreeUtil(pre,post,preIndex,l,i,size);root->right=constructTreeUtil(pre,post,preIndex,i+1,h-1,size);}returnroot;}// Function to construct Binary Tree from preorder and postorderNode*constructTree(vector<int>&pre,vector<int>&post){intpreIndex=0;returnconstructTreeUtil(pre,post,preIndex,0,pre.size()-1,pre.size());}intgetHeight(Node*root,inth){if(root==nullptr)returnh-1;returnmax(getHeight(root->left,h+1),getHeight(root->right,h+1));}voidlevelOrder(Node*root){queue<pair<Node*,int>>q;q.push({root,0});intlastLevel=0;// function to get the height of treeintheight=getHeight(root,0);// printing the level order of treewhile(!q.empty()){autotop=q.front();q.pop();Node*node=top.first;intlvl=top.second;if(lvl>lastLevel){cout<<"\n";lastLevel=lvl;}// all levels are printedif(lvl>height)break;if(node->data!=-1)cout<<node->data<<" ";// printing null nodeelsecout<<"N ";// null node has no childrenif(node->data==-1)continue;if(node->left==nullptr)q.push({newNode(-1),lvl+1});elseq.push({node->left,lvl+1});if(node->right==nullptr)q.push({newNode(-1),lvl+1});elseq.push({node->right,lvl+1});}}intmain(){vector<int>pre={1,2,4,8,9,5,3,6,7};vector<int>post={8,9,4,5,2,6,7,3,1};Node*root=constructTree(pre,post);levelOrder(root);return0;}
Java
importjava.util.LinkedList;importjava.util.Queue;importjava.util.List;importjava.util.ArrayList;// Node StructureclassNode{intdata;Nodeleft,right;Node(intx){data=x;left=right=null;}}classGFG{// Recursive function to construct// binary tree from preorder and postorderstaticNodeconstructTreeUtil(int[]pre,int[]post,int[]preIndex,intl,inth,intsize){if(preIndex[0]>=size||l>h)returnnull;// Create root node from current preorder elementNoderoot=newNode(pre[preIndex[0]++]);// If there is only one element, return it as leaf nodeif(l==h)returnroot;// Find the next preorder element in postorder to // split left and right subtreesinti;for(i=l;i<=h;i++)if(pre[preIndex[0]]==post[i])break;if(i<=h){// Recursively construct left and right subtreesroot.left=constructTreeUtil(pre,post,preIndex,l,i,size);root.right=constructTreeUtil(pre,post,preIndex,i+1,h-1,size);}returnroot;}// Main function to construct binary treestaticNodeconstructTree(int[]pre,int[]post){int[]preIndex={0};intsize=pre.length;returnconstructTreeUtil(pre,post,preIndex,0,size-1,size);}staticintgetHeight(Noderoot,inth){if(root==null)returnh-1;returnMath.max(getHeight(root.left,h+1),getHeight(root.right,h+1));}staticvoidlevelOrder(Noderoot){Queue<List<Object>>queue=newLinkedList<>();queue.offer(List.of(root,0));intlastLevel=0;// function to get the height of treeintheight=getHeight(root,0);// printing the level order of treewhile(!queue.isEmpty()){List<Object>top=queue.poll();Nodenode=(Node)top.get(0);intlvl=(int)top.get(1);if(lvl>lastLevel){System.out.println();lastLevel=lvl;}// all levels are printedif(lvl>height)break;// printing null nodeSystem.out.print((node.data==-1?"N":node.data)+" ");// null node has no childrenif(node.data==-1)continue;if(node.left==null)queue.offer(List.of(newNode(-1),lvl+1));elsequeue.offer(List.of(node.left,lvl+1));if(node.right==null)queue.offer(List.of(newNode(-1),lvl+1));elsequeue.offer(List.of(node.right,lvl+1));}}publicstaticvoidmain(String[]args){int[]pre={1,2,4,8,9,5,3,6,7};int[]post={8,9,4,5,2,6,7,3,1};Noderoot=constructTree(pre,post);levelOrder(root);}}
Python
fromcollectionsimportdeque# Node StructureclassNode:def__init__(self,x):self.data=xself.left=Noneself.right=None# Recursive function to construct# binary tree from preorder and postorderdefconstructTreeUtil(pre,post,preIndex,l,h,size):ifpreIndex[0]>=sizeorl>h:returnNone# Create root node from current preorder elementroot=Node(pre[preIndex[0]])preIndex[0]+=1# If there is only one element, return it as leaf nodeifl==h:returnroot# Find the next preorder element in # postorder to split left and right subtreesi=lwhilei<=handpre[preIndex[0]]!=post[i]:i+=1ifi<=h:# Recursively construct left and right subtreesroot.left=constructTreeUtil(pre,post,preIndex,l,i,size)root.right=constructTreeUtil(pre,post,preIndex,i+1,h-1,size)returnroot# Main function to construct binary treedefconstructTree(pre,post):preIndex=[0]size=len(pre)returnconstructTreeUtil(pre,post,preIndex,0,size-1,size)defgetHeight(root,h):ifrootisNone:returnh-1returnmax(getHeight(root.left,h+1),getHeight(root.right,h+1))deflevelOrder(root):queue=deque([[root,0]])lastLevel=0# function to get the height of treeheight=getHeight(root,0)# printing the level order of treewhilequeue:node,lvl=queue.popleft()iflvl>lastLevel:print()lastLevel=lvl# all levels are printediflvl>height:break# printing null nodeprint("N"ifnode.data==-1elsenode.data,end=" ")# null node has no childrenifnode.data==-1:continueifnode.leftisNone:queue.append([Node(-1),lvl+1])else:queue.append([node.left,lvl+1])ifnode.rightisNone:queue.append([Node(-1),lvl+1])else:queue.append([node.right,lvl+1])if__name__=="__main__":pre=[1,2,4,8,9,5,3,6,7]post=[8,9,4,5,2,6,7,3,1]root=constructTree(pre,post)levelOrder(root)
C#
usingSystem;usingSystem.Collections.Generic;// Node StructureclassNode{publicintdata;publicNodeleft,right;publicNode(intx){data=x;left=right=null;}}classGFG{// Recursive function to construct binary tree// from preorder and postorderstaticNodeconstructTreeUtil(int[]pre,int[]post,refintpreIndex,intl,inth,intsize){if(preIndex>=size||l>h)returnnull;// Create root node from current preorder elementNoderoot=newNode(pre[preIndex++]);// If there is only one element, return it as leaf nodeif(l==h)returnroot;// Find the next preorder element in postorder// to split left and right subtreesinti=l;while(i<=h&&pre[preIndex]!=post[i])i++;if(i<=h){// Recursively construct left and right subtreesroot.left=constructTreeUtil(pre,post,refpreIndex,l,i,size);root.right=constructTreeUtil(pre,post,refpreIndex,i+1,h-1,size);}returnroot;}// Main function to construct full binary treestaticNodeconstructTree(int[]pre,int[]post){intpreIndex=0;intsize=pre.Length;returnconstructTreeUtil(pre,post,refpreIndex,0,size-1,size);}staticintgetHeight(Noderoot,inth){if(root==null)returnh-1;returnMath.Max(getHeight(root.left,h+1),getHeight(root.right,h+1));}staticvoidlevelOrder(Noderoot){Queue<(Node,int)>queue=newQueue<(Node,int)>();queue.Enqueue((root,0));intlastLevel=0;// function to get the height of treeintheight=getHeight(root,0);// printing the level order of treewhile(queue.Count>0){var(node,lvl)=queue.Dequeue();if(lvl>lastLevel){Console.WriteLine();lastLevel=lvl;}// all levels are printedif(lvl>height)break;// printing null nodeConsole.Write((node.data==-1?"N":node.data.ToString())+" ");// null node has no childrenif(node.data==-1)continue;if(node.left==null)queue.Enqueue((newNode(-1),lvl+1));elsequeue.Enqueue((node.left,lvl+1));if(node.right==null)queue.Enqueue((newNode(-1),lvl+1));elsequeue.Enqueue((node.right,lvl+1));}}publicstaticvoidMain(){int[]pre={1,2,4,8,9,5,3,6,7};int[]post={8,9,4,5,2,6,7,3,1};Noderoot=constructTree(pre,post);levelOrder(root);}}
JavaScript
// Queue nodeclassQNode{constructor(data){this.data=data;this.next=null;}}// Node StructureclassNode{constructor(data){this.data=data;this.left=null;this.right=null;}}classQueue{constructor(){this.front=null;this.rear=null;}isEmpty(){returnthis.front===null;}enqueue(x){letnewNode=newQNode(x);if(this.rear===null){this.front=this.rear=newNode;return;}this.rear.next=newNode;this.rear=newNode;}dequeue(){if(this.front===null)returnnull;lettemp=this.front;this.front=this.front.next;if(this.front===null)this.rear=null;returntemp.data;}}// Recursive function to construct // binary tree from preorder and postorderfunctionconstructTreeUtil(pre,post,preIndex,l,h,size){if(preIndex.index>=size||l>h)returnnull;// Create root node from current preorder elementletroot=newNode(pre[preIndex.index++]);// If there is only one element, return it as leaf nodeif(l===h)returnroot;// Find the next preorder element in// postorder to split left and right subtreesleti=l;while(i<=h&&pre[preIndex.index]!==post[i])i++;if(i<=h){// Recursively construct left and right subtreesroot.left=constructTreeUtil(pre,post,preIndex,l,i,size);root.right=constructTreeUtil(pre,post,preIndex,i+1,h-1,size);}returnroot;}// Main function to construct full binary treefunctionconstructTree(pre,post){// Using object for pass-by-referenceletpreIndex={index:0};letsize=pre.length;returnconstructTreeUtil(pre,post,preIndex,0,size-1,size);}functiongetHeight(root,h){if(root===null)returnh-1;returnMath.max(getHeight(root.left,h+1),getHeight(root.right,h+1));}functionlevelOrder(root){letqueue=[];queue.push([root,0]);letlastLevel=0;// get the height of treeletheight=getHeight(root,0);// printing the level order of treewhile(queue.length>0){let[node,lvl]=queue.shift();if(lvl>lastLevel){console.log("");lastLevel=lvl;}// all levels are printedif(lvl>height)break;// printing null nodeprocess.stdout.write((node.data===-1?"N":node.data)+" ");// null node has no childrenif(node.data===-1)continue;if(node.left===null)queue.push([newNode(-1),lvl+1]);elsequeue.push([node.left,lvl+1]);if(node.right===null)queue.push([newNode(-1),lvl+1]);elsequeue.push([node.right,lvl+1]);}}//Driver Codeconstpre=[1,2,4,8,9,5,3,6,7];constpost=[8,9,4,5,2,6,7,3,1];constroot=constructTree(pre,post);levelOrder(root);
Output
1
2 3
4 5 6 7
8 9 N N N N N N
[Expected Approach] Using HashMap and Recursion - O(n) Time and O(n) Space
The idea is to use the properties of preorder (NLR) and postorder (LRN) traversals. In preorder, the first element is always the root, which serves as the starting point for constructing the tree. The next element in preorder belongs to the left subtree, and its position in the postorder array helps to divide the tree into two parts: the elements before this position form the left subtree, and the elements after it form the right subtree. To find this position efficiently, we use a HashMap for constant-time lookup, and then recursively split the array to build the left and right subtrees and rebuild the entire tree.
C++
#include<iostream>#include<queue>#include<unordered_map>#include<vector>usingnamespacestd;// Node StructureclassNode{public:intdata;Node*left;Node*right;Node(intx){data=x;left=right=nullptr;}};// Recursive function to construct binary// tree from preorder and postorderNode*constructTreeUtil(vector<int>&pre,vector<int>&post,int&preIndex,intl,inth,intsize,unordered_map<int,int>&postMap){if(preIndex>=size||l>h)returnnullptr;Node*root=newNode(pre[preIndex++]);// If there is only one element,// return it as leaf nodeif(l==h)returnroot;// Find the next preorder element// in postorder using hashmapinti=postMap[pre[preIndex]];if(i<=h){root->left=constructTreeUtil(pre,post,preIndex,l,i,size,postMap);root->right=constructTreeUtil(pre,post,preIndex,i+1,h-1,size,postMap);}returnroot;}// Function to construct Binary Tree// from preorder and postorderNode*constructTree(vector<int>&pre,vector<int>&post){intpreIndex=0;intsize=pre.size();// Build hashmap for postorder elementunordered_map<int,int>postMap;for(inti=0;i<size;i++)postMap[post[i]]=i;returnconstructTreeUtil(pre,post,preIndex,0,size-1,size,postMap);}// Function to get the height of the treeintgetHeight(Node*root,inth){if(root==nullptr)returnh-1;returnmax(getHeight(root->left,h+1),getHeight(root->right,h+1));}// Level Order traversalvoidlevelOrder(Node*root){queue<pair<Node*,int>>q;q.push({root,0});intlastLevel=0;intheight=getHeight(root,0);while(!q.empty()){autotop=q.front();q.pop();Node*node=top.first;intlvl=top.second;if(lvl>lastLevel){cout<<"\n";lastLevel=lvl;}// all levels are printedif(lvl>height)break;// print null node as "N"if(node->data!=-1)cout<<node->data<<" ";elsecout<<"N ";// null nodes have no childrenif(node->data==-1)continue;if(node->left==nullptr)q.push({newNode(-1),lvl+1});elseq.push({node->left,lvl+1});if(node->right==nullptr)q.push({newNode(-1),lvl+1});elseq.push({node->right,lvl+1});}}intmain(){vector<int>pre={1,2,4,8,9,5,3,6,7};vector<int>post={8,9,4,5,2,6,7,3,1};Node*root=constructTree(pre,post);levelOrder(root);return0;}
Java
importjava.util.ArrayList;importjava.util.HashMap;importjava.util.LinkedList;importjava.util.Queue;// Node structureclassNode{intdata;Nodeleft,right;Node(intx){data=x;left=right=null;}}publicclassConstructTree{// Recursive function to construct binary// tree from preorder and postorderstaticNodeconstructTreeUtil(int[]pre,int[]post,int[]preIndex,intl,inth,intsize,HashMap<Integer,Integer>postMap){if(preIndex[0]>=size||l>h)returnnull;Noderoot=newNode(pre[preIndex[0]++]);// If there is only one element, // return it as leaf nodeif(l==h)returnroot;// Find the next preorder element in // postorder using hashmapinti=postMap.get(pre[preIndex[0]]);if(i<=h){// Recursively construct left and right subtreesroot.left=constructTreeUtil(pre,post,preIndex,l,i,size,postMap);root.right=constructTreeUtil(pre,post,preIndex,i+1,h-1,size,postMap);}returnroot;}// Function to construct Binary Tree// from preorder and postorderstaticNodeconstructTree(int[]pre,int[]post){intsize=pre.length;int[]preIndex={0};// Build hashmap for postorder element HashMap<Integer,Integer>postMap=newHashMap<>();for(inti=0;i<size;i++)postMap.put(post[i],i);returnconstructTreeUtil(pre,post,preIndex,0,size-1,size,postMap);}// Function to get the height of treestaticintgetHeight(Noderoot,inth){if(root==null)returnh-1;returnMath.max(getHeight(root.left,h+1),getHeight(root.right,h+1));}// Level Order traversalstaticvoidlevelOrder(Noderoot){Queue<Node>q=newLinkedList<>();q.add(root);intlastLevel=0;intheight=getHeight(root,0);classPair{Nodenode;intlevel;Pair(Noden,intl){node=n;level=l;}}Queue<Pair>pq=newLinkedList<>();pq.add(newPair(root,0));while(!pq.isEmpty()){Pairtop=pq.poll();Nodenode=top.node;intlvl=top.level;if(lvl>lastLevel){System.out.println();lastLevel=lvl;}// all levels are printedif(lvl>height)break;// print null node as "N"if(node.data!=-1)System.out.print(node.data+" ");elseSystem.out.print("N ");// Null nodes have no childrenif(node.data==-1)continue;if(node.left==null)pq.add(newPair(newNode(-1),lvl+1));elsepq.add(newPair(node.left,lvl+1));if(node.right==null)pq.add(newPair(newNode(-1),lvl+1));elsepq.add(newPair(node.right,lvl+1));}}publicstaticvoidmain(String[]args){int[]pre={1,2,4,8,9,5,3,6,7};int[]post={8,9,4,5,2,6,7,3,1};Noderoot=constructTree(pre,post);levelOrder(root);}}
Python
# Node structureclassNode:def__init__(self,data):self.data=dataself.left=Noneself.right=None# Recursive function to construct binary tree from preorder and postorderdefconstructTreeUtil(pre,post,preIndex,l,h,postMap):ifpreIndex[0]>=len(pre)orl>h:returnNoneroot=Node(pre[preIndex[0]])preIndex[0]+=1# If there is only one element,# return it as leaf nodeifl==h:returnroot# Find the next preorder element# in postorder using hashmapi=postMap[pre[preIndex[0]]]ifi<=h:root.left=constructTreeUtil(pre,post,preIndex,l,i,postMap)root.right=constructTreeUtil(pre,post,preIndex,i+1,h-1,postMap)returnroot# Function to construct Binary Tree# from preorder and postorderdefconstructTree(pre,post):# Build hashmap for postorder element postMap={val:idxforidx,valinenumerate(post)}preIndex=[0]returnconstructTreeUtil(pre,post,preIndex,0,len(pre)-1,postMap)# Function to get the height of the treedefgetHeight(root,h):ifrootisNone:returnh-1returnmax(getHeight(root.left,h+1),getHeight(root.right,h+1))# Level Order traversal with printing null nodes as "N"fromcollectionsimportdequedeflevelOrder(root):q=deque()q.append((root,0))lastLevel=0height=getHeight(root,0)whileq:node,lvl=q.popleft()iflvl>lastLevel:print()lastLevel=lvl# all levels are printedif(lvl>height):break# print null node as "N"print(node.dataifnode.data!=-1else"N",end=" ")# Null nodes do not have childrenifnode.data==-1:continueq.append((node.leftifnode.leftelseNode(-1),lvl+1))q.append((node.rightifnode.rightelseNode(-1),lvl+1))print()if__name__=="__main__":pre=[1,2,4,8,9,5,3,6,7]post=[8,9,4,5,2,6,7,3,1]root=constructTree(pre,post)levelOrder(root)
C#
usingSystem;usingSystem.Collections.Generic;// Node StructureclassNode{publicintdata;publicNodeleft;publicNoderight;publicNode(intx){data=x;left=right=null;}}classGFG{// Recursive function to construct binary// tree from preorder and postorderstaticNodeconstructTreeUtil(int[]pre,int[]post,refintpreIndex,intl,inth,intsize,Dictionary<int,int>postMap){if(preIndex>=size||l>h)returnnull;Noderoot=newNode(pre[preIndex++]);// If there is only one element,// return it as leaf nodeif(l==h)returnroot;// Find the next preorder element// in postorder using hashmapinti=postMap[pre[preIndex]];if(i<=h){root.left=constructTreeUtil(pre,post,refpreIndex,l,i,size,postMap);root.right=constructTreeUtil(pre,post,refpreIndex,i+1,h-1,size,postMap);}returnroot;}// Function to construct Binary Tree // from preorder and postorderstaticNodeconstructTree(int[]pre,int[]post){intpreIndex=0;intsize=pre.Length;// Build hashmap for postorder element Dictionary<int,int>postMap=newDictionary<int,int>();for(inti=0;i<size;i++)postMap[post[i]]=i;returnconstructTreeUtil(pre,post,refpreIndex,0,size-1,size,postMap);}// Function to get the height of the treestaticintgetHeight(Noderoot,inth){if(root==null)returnh-1;returnMath.Max(getHeight(root.left,h+1),getHeight(root.right,h+1));}// Level Order traversalstaticvoidlevelOrder(Noderoot){Queue<(Node,int)>q=newQueue<(Node,int)>();q.Enqueue((root,0));intlastLevel=0;intheight=getHeight(root,0);while(q.Count>0){vartop=q.Dequeue();Nodenode=top.Item1;intlvl=top.Item2;if(lvl>lastLevel){Console.WriteLine();lastLevel=lvl;}// all levels are printedif(lvl>height)break;// print null node as "N"if(node.data!=-1)Console.Write(node.data+" ");elseConsole.Write("N ");// null nodes have no childrenif(node.data==-1)continue;if(node.left==null)q.Enqueue((newNode(-1),lvl+1));elseq.Enqueue((node.left,lvl+1));if(node.right==null)q.Enqueue((newNode(-1),lvl+1));elseq.Enqueue((node.right,lvl+1));}}// Driver CodestaticvoidMain(){int[]pre={1,2,4,8,9,5,3,6,7};int[]post={8,9,4,5,2,6,7,3,1};Noderoot=constructTree(pre,post);levelOrder(root);}}
JavaScript
// Node StructureclassNode{constructor(x){this.data=x;this.left=null;this.right=null;}}// Custom Queue implementationclassQueue{constructor(){this.items=[];this.frontIndex=0;}push(element){this.items.push(element);}pop(){if(this.isEmpty())returnnull;returnthis.items[this.frontIndex++];}front(){returnthis.items[this.frontIndex];}isEmpty(){returnthis.frontIndex>=this.items.length;}}// Recursive function to construct binary// tree from preorder and postorderfunctionconstructTreeUtil(pre,post,preIndex,l,h,size,postMap){if(preIndex.value>=size||l>h)returnnull;letroot=newNode(pre[preIndex.value++]);// If there is only one element,// return it as leaf nodeif(l===h)returnroot;// Find the next preorder element// in postorder using hashmapleti=postMap.get(pre[preIndex.value]);if(i<=h){root.left=constructTreeUtil(pre,post,preIndex,l,i,size,postMap);root.right=constructTreeUtil(pre,post,preIndex,i+1,h-1,size,postMap);}returnroot;}// Function to construct Binary Tree // from preorder and postorderfunctionconstructTree(pre,post){letpreIndex={value:0};letsize=pre.length;// Build hashmap for postorder element letpostMap=newMap();for(leti=0;i<size;i++)postMap.set(post[i],i);returnconstructTreeUtil(pre,post,preIndex,0,size-1,size,postMap);}// Function to get the height of the treefunctiongetHeight(root,h){if(root===null)returnh-1;returnMath.max(getHeight(root.left,h+1),getHeight(root.right,h+1));}// Level Order traversalfunctionlevelOrder(root){letq=newQueue();q.push([root,0]);letlastLevel=0;letheight=getHeight(root,0);while(!q.isEmpty()){let[node,lvl]=q.pop();if(lvl>lastLevel){console.log();lastLevel=lvl;}// all levels are printedif(lvl>height)break;// print null node as "N"if(node.data!==-1)process.stdout.write(node.data+" ");elseprocess.stdout.write("N ");// null nodes have no childrenif(node.data===-1)continue;if(node.left===null)q.push([newNode(-1),lvl+1]);elseq.push([node.left,lvl+1]);if(node.right===null)q.push([newNode(-1),lvl+1]);elseq.push([node.right,lvl+1]);}}// Driver Code letpre=[1,2,4,8,9,5,3,6,7];letpost=[8,9,4,5,2,6,7,3,1];letroot=constructTree(pre,post);levelOrder(root);