Construct a Binary Search Tree from given postorder

Last Updated : 20 Jun, 2026

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.

Try It Yourself
redirect icon

[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
C++
#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;
}
Java
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);
    }
}
Python
# 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)
C#
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);
    }
}
JavaScript
// 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.
C++
/* 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;
}
Java
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);
    }
}
Python
# 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)
C#
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);
    }
}
JavaScript
// 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 


Comment