Given postorder traversal of a binary search tree, construct the BST.
Input: 1 7 5 50 40 10
Output: 1 5 7 10 40 50
Explanation: The BST for the given post order traversal is:![]()
Thus the inorder traversal of BST is: 1 5 7 10 40 50.
Table of Content
[Naive Approach] Using Repeated BST Insertion – O(n²) Time and O(n) Space
The idea is to construct the BST by inserting nodes one by one from the postorder traversal array in reverse order. Since the last element of postorder traversal is the root of the BST, inserting elements from right to left recreates the original BST structure. Each insertion follows normal BST insertion rules.
- Start with an empty BST
- Traverse the postorder array from end to beginning
- Insert each element into the BST using standard BST insertion
- Perform inorder traversal to verify the constructed BST
#include <bits/stdc++.h>
using namespace std;
// Binary Tree Node
class Node
{
public:
int data;
Node *left, *right;
Node(int value)
{
data = value;
left = right = nullptr;
}
};
// Function to insert node in BST
Node* insert(Node* root, int key)
{
// If tree is empty
if(root == nullptr)
{
return new Node(key);
}
// Move to left subtree
if(key < root->data)
{
root->left = insert(root->left, key);
}
else
{
// Move to right subtree
root->right = insert(root->right, key);
}
return root;
}
// Naive function to construct BST
Node* constructTree(vector<int>& post)
{
Node* root = nullptr;
// Insert all elements one by one
for(int i = post.size() - 1; i >= 0; i--)
{
root = insert(root, post[i]);
}
return root;
}
// Function for inorder traversal
void printInorder(Node* root)
{
if(root == nullptr)
{
return;
}
printInorder(root->left);
cout << root->data << " ";
printInorder(root->right);
}
// Driver code
int main()
{
vector<int> post = {1, 7, 5, 50, 40, 10};
Node* root = constructTree(post);
cout << "Inorder traversal of the constructed BST:\n";
printInorder(root);
return 0;
}
import java.util.*;
class GFG {
// Binary Tree Node
static class Node
{
int data;
Node left, right;
Node(int value)
{
data = value;
left = right = null;
}
}
// Function to insert node in BST
static Node insert(Node root, int key)
{
// If tree is empty
if(root == null)
{
return new Node(key);
}
// Move to left subtree
if(key < root.data)
{
root.left = insert(root.left, key);
}
else
{
// Move to right subtree
root.right = insert(root.right, key);
}
return root;
}
// Naive function to construct BST
static Node constructTree(ArrayList<Integer> post)
{
Node root = null;
// Insert all elements one by one
for(int i = post.size() - 1; i >= 0; i--)
{
root = insert(root, post.get(i));
}
return root;
}
// Function for inorder traversal
static void printInorder(Node root)
{
if(root == null)
{
return;
}
printInorder(root.left);
System.out.print(root.data + " ");
printInorder(root.right);
}
// Driver code
public static void main(String[] args)
{
ArrayList<Integer> post = new ArrayList<>(
Arrays.asList(1, 7, 5, 50, 40, 10));
Node root = constructTree(post);
System.out.println(
"Inorder traversal of the constructed BST:");
printInorder(root);
}
}
# Binary Tree Node
class Node:
def __init__(self, value):
self.data = value
self.left = None
self.right = None
# Function to insert node in BST
def insert(root, key):
# If tree is empty
if root is None:
return Node(key)
# Move to left subtree
if key < root.data:
root.left = insert(root.left, key)
else:
# Move to right subtree
root.right = insert(root.right, key)
return root
# Naive function to construct BST
def constructTree(post):
root = None
# Insert all elements one by one
for i in range(len(post) - 1, -1, -1):
root = insert(root, post[i])
return root
# Function for inorder traversal
def printInorder(root):
if root is None:
return
printInorder(root.left)
print(root.data, end=" ")
printInorder(root.right)
# Driver code
post = [1, 7, 5, 50, 40, 10]
root = constructTree(post)
print("Inorder traversal of the constructed BST:")
printInorder(root)
using System;
using System.Collections.Generic;
class GFG {
// Binary Tree Node
class Node
{
public int data;
public Node left, right;
public Node(int value)
{
data = value;
left = right = null;
}
}
// Function to insert node in BST
static Node insert(Node root, int key)
{
// If tree is empty
if(root == null)
{
return new Node(key);
}
// Move to left subtree
if(key < root.data)
{
root.left = insert(root.left, key);
}
else
{
// Move to right subtree
root.right = insert(root.right, key);
}
return root;
}
// Naive function to construct BST
static Node constructTree(List<int> post)
{
Node root = null;
// Insert all elements one by one
for(int i = post.Count - 1; i >= 0; i--)
{
root = insert(root, post[i]);
}
return root;
}
// Function for inorder traversal
static void printInorder(Node root)
{
if(root == null)
{
return;
}
printInorder(root.left);
Console.Write(root.data + " ");
printInorder(root.right);
}
// Driver code
static void Main()
{
List<int> post = new List<int>()
{
1, 7, 5, 50, 40, 10
};
Node root = constructTree(post);
Console.WriteLine(
"Inorder traversal of the constructed BST:");
printInorder(root);
}
}
// Binary Tree Node
class Node
{
constructor(value)
{
this.data = value;
this.left = null;
this.right = null;
}
}
// Function to insert node in BST
function insert(root, key)
{
// If tree is empty
if(root === null)
{
return new Node(key);
}
// Move to left subtree
if(key < root.data)
{
root.left = insert(root.left, key);
}
else
{
// Move to right subtree
root.right = insert(root.right, key);
}
return root;
}
// Naive function to construct BST
function constructTree(post)
{
let root = null;
// Insert all elements one by one
for(let i = post.length - 1; i >= 0; i--)
{
root = insert(root, post[i]);
}
return root;
}
// Function for inorder traversal
function printInorder(root)
{
if(root === null)
{
return;
}
printInorder(root.left);
process.stdout.write(root.data + " ");
printInorder(root.right);
}
// Driver code
let post = [1, 7, 5, 50, 40, 10];
let root = constructTree(post);
console.log("Inorder traversal of the constructed BST:");
printInorder(root);
Output
Inorder traversal of the constructed BST: 1 5 7 10 40 50
[Optimal Approach] Using Range Boundaries – O(n) Time and O(n) Space
Since postorder traversal follows
left -> right -> root, we process elements from the end because the last element is always the root. Using valid minimum and maximum ranges for each subtree, we determine whether a node belongs to the current subtree and recursively build the right and left subtrees.
- Start from the last element of postorder traversal as the root
- Maintain valid range
(min, max)for each subtree. Initially the range for root is passed as [-INF, +INF] - If current value lies within range, create node and decrease index
- Recursively construct right subtree first, then left subtree. Pass the range as [min, root->key] for left subtree and [root->key, max] for right subtree.
/* A O(n) program for construction of
BST from postorder traversal */
#include <bits/stdc++.h>
using namespace std;
/* A binary tree node has data,
pointer to left child and a
pointer to right child */
class Node
{
public:
int data;
Node *left, *right;
Node(int value)
{
data = value;
left = right = nullptr;
}
};
// A recursive function to construct
// BST from post[]. postIndex is used
// to keep track of index in post[].
Node* constructTreeUtil(vector<int>& post, int& postIndex,
int key, int mn, int mx)
{
// Base case
if (postIndex < 0)
return nullptr;
Node* root = nullptr;
// If current element of post[] is
// in range, then only it is part
// of current subtree
if (key > mn && key < mx)
{
// Allocate memory for root of this
// subtree and decrement postIndex
root = new Node(key);
postIndex--;
if (postIndex >= 0)
{
// All nodes which are in range {key..mx}
// will go in right subtree
root->right = constructTreeUtil(post, postIndex,
post[postIndex],
key, mx);
// All nodes which are in range {mn..key}
// will go in left subtree
root->left = constructTreeUtil(post, postIndex,
post[postIndex],
mn, key);
}
}
return root;
}
// The main function to construct BST
// from given postorder traversal
Node* constructTree(vector<int>& post)
{
int postIndex = post.size() - 1;
return constructTreeUtil(post, postIndex,
post[postIndex],
INT_MIN, INT_MAX);
}
// A utility function to print
// inorder traversal of a Binary Tree
void printInorder(Node* root)
{
if (root == nullptr)
return;
printInorder(root->left);
cout << root->data << " ";
printInorder(root->right);
}
// Driver Code
int main()
{
vector<int> post = {1, 7, 5, 50, 40, 10};
Node *root = constructTree(post);
cout << "Inorder traversal of "
<< "the constructed tree:\n";
printInorder(root);
return 0;
}
import java.util.*;
class GFG {
/* A binary tree node has data,
pointer to left child and a
pointer to right child */
static class Node
{
int data;
Node left, right;
Node(int value)
{
data = value;
left = right = null;
}
}
// A recursive function to construct
// BST from post[]. postIndex is used
// to keep track of index in post[].
static Node constructTreeUtil(ArrayList<Integer> post,
int[] postIndex,
int key, int mn, int mx)
{
// Base case
if (postIndex[0] < 0)
return null;
Node root = null;
// If current element of post[]
// is in range, then only it is part
// of current subtree
if (key > mn && key < mx)
{
// Allocate memory for root of this
// subtree and decrement postIndex
root = new Node(key);
postIndex[0]--;
if (postIndex[0] >= 0)
{
// All nodes which are in range {key..mx}
// will go in right subtree
root.right = constructTreeUtil(post,
postIndex,
post.get(postIndex[0]),
key, mx);
// All nodes which are in range {mn..key}
// will go in left subtree
root.left = constructTreeUtil(post,
postIndex,
post.get(postIndex[0]),
mn, key);
}
}
return root;
}
// The main function to construct BST
// from given postorder traversal
static Node constructTree(ArrayList<Integer> post)
{
int[] postIndex = {post.size() - 1};
return constructTreeUtil(post,
postIndex,
post.get(postIndex[0]),
Integer.MIN_VALUE,
Integer.MAX_VALUE);
}
// A utility function to print
// inorder traversal of a Binary Tree
static void printInorder(Node root)
{
if (root == null)
return;
printInorder(root.left);
System.out.print(root.data + " ");
printInorder(root.right);
}
// Driver Code
public static void main(String[] args)
{
ArrayList<Integer> post = new ArrayList<>(
Arrays.asList(1, 7, 5, 50, 40, 10));
Node root = constructTree(post);
System.out.println("Inorder traversal of "
+ "the constructed tree:");
printInorder(root);
}
}
# A binary tree node has data,
# pointer to left child and a
# pointer to right child
class Node:
def __init__(self, value):
self.data = value
self.left = None
self.right = None
# A recursive function to construct
# BST from post[]. postIndex is used
# to keep track of index in post[].
def constructTreeUtil(post, postIndex,
key, mn, mx):
# Base case
if postIndex[0] < 0:
return None
root = None
# If current element of post[]
# is in range, then only it is part
# of current subtree
if key > mn and key < mx:
# Allocate memory for root of this
# subtree and decrement postIndex
root = Node(key)
postIndex[0] -= 1
if postIndex[0] >= 0:
# All nodes which are in range
# {key..mx} will go in right subtree
root.right = constructTreeUtil(
post,
postIndex,
post[postIndex[0]],
key,
mx
)
# All nodes which are in range
# {mn..key} will go in left subtree
root.left = constructTreeUtil(
post,
postIndex,
post[postIndex[0]],
mn,
key
)
return root
# The main function to construct BST
# from given postorder traversal
def constructTree(post):
postIndex = [len(post) - 1]
return constructTreeUtil(
post,
postIndex,
post[postIndex[0]],
float('-inf'),
float('inf')
)
# A utility function to print
# inorder traversal of a Binary Tree
def printInorder(root):
if root is None:
return
printInorder(root.left)
print(root.data, end=" ")
printInorder(root.right)
# Driver Code
post = [1, 7, 5, 50, 40, 10]
root = constructTree(post)
print("Inorder traversal of the constructed tree:")
printInorder(root)
using System;
using System.Collections.Generic;
class GFG {
/* A binary tree node has data,
pointer to left child and a
pointer to right child */
class Node
{
public int data;
public Node left, right;
public Node(int value)
{
data = value;
left = right = null;
}
}
// A recursive function to construct
// BST from post[]. postIndex is used
// to keep track of index in post[].
static Node constructTreeUtil(List<int> post,
int[] postIndex,
int key, int mn, int mx)
{
// Base case
if (postIndex[0] < 0)
return null;
Node root = null;
// If current element of post[]
// is in range, then only it is part
// of current subtree
if (key > mn && key < mx)
{
// Allocate memory for root of this
// subtree and decrement postIndex
root = new Node(key);
postIndex[0]--;
if (postIndex[0] >= 0)
{
// All nodes which are in range {key..mx}
// will go in right subtree
root.right = constructTreeUtil(
post,
postIndex,
post[postIndex[0]],
key,
mx
);
// All nodes which are in range {mn..key}
// will go in left subtree
root.left = constructTreeUtil(
post,
postIndex,
post[postIndex[0]],
mn,
key
);
}
}
return root;
}
// The main function to construct BST
// from given postorder traversal
static Node constructTree(List<int> post)
{
int[] postIndex = { post.Count - 1 };
return constructTreeUtil(
post,
postIndex,
post[postIndex[0]],
int.MinValue,
int.MaxValue
);
}
// A utility function to print
// inorder traversal of a Binary Tree
static void printInorder(Node root)
{
if (root == null)
return;
printInorder(root.left);
Console.Write(root.data + " ");
printInorder(root.right);
}
// Driver Code
static void Main()
{
List<int> post = new List<int>()
{
1, 7, 5, 50, 40, 10
};
Node root = constructTree(post);
Console.WriteLine("Inorder traversal of "
+ "the constructed tree:");
printInorder(root);
}
}
// A binary tree node has data,
// pointer to left child and a
// pointer to right child
class Node
{
constructor(value)
{
this.data = value;
this.left = null;
this.right = null;
}
}
// A recursive function to construct
// BST from post[]. postIndex is used
// to keep track of index in post[].
function constructTreeUtil(post, postIndex,
key, mn, mx)
{
// Base case
if (postIndex.value < 0)
return null;
let root = null;
// If current element of post[]
// is in range, then only it is part
// of current subtree
if (key > mn && key < mx)
{
// Allocate memory for root of this
// subtree and decrement postIndex
root = new Node(key);
postIndex.value--;
if (postIndex.value >= 0)
{
// All nodes which are in range
// {key..mx} will go in right subtree
root.right = constructTreeUtil(
post,
postIndex,
post[postIndex.value],
key,
mx
);
// All nodes which are in range
// {mn..key} will go in left subtree
root.left = constructTreeUtil(
post,
postIndex,
post[postIndex.value],
mn,
key
);
}
}
return root;
}
// The main function to construct BST
// from given postorder traversal
function constructTree(post)
{
let postIndex = { value: post.length - 1 };
return constructTreeUtil(
post,
postIndex,
post[postIndex.value],
-Infinity,
Infinity
);
}
// A utility function to print
// inorder traversal of a Binary Tree
function printInorder(root)
{
if (root === null)
return;
printInorder(root.left);
process.stdout.write(root.data + " ");
printInorder(root.right);
}
// Driver Code
let post = [1, 7, 5, 50, 40, 10];
let root = constructTree(post);
console.log("Inorder traversal of the constructed tree:");
printInorder(root);
Output
Inorder traversal of the constructed tree: 1 5 7 10 40 50
