Construct all possible BSTs for keys 1 to N
Last Updated :
23 Jul, 2025
Given an integer n, the task is to generate all possible Binary Search Trees (BSTs) that can be constructed using keys from 1 to n and print their preorder traversal.
Examples:
Input: n = 2
Output:
1 2
2 1
Input: n = 3
Output:
1 2 3
1 3 2
2 1 3
3 1 2
3 2 1
How many structurally unique BSTs can be formed with keys from 1 to n?
- The key observation is that for any i-th number chosen as the root, all numbers from 1 to i-1 must be in the left subtree (since they are smaller than the root), and all numbers from i+1 to n must be in the right subtree (since they are larger than the root).
- If the numbers from 1 to i-1 can form x different trees and the numbers from i+1 to n can form y different trees, then for the i-th number as root, we can have x * y total unique BSTs.
- Since we can choose any number from 1 to n as the root, we iterate over each possible root (from 1 to n) and calculate the total number of unique BSTs by summing up the product of the number of left and right subtrees for each root.
- Upon observation, the number of structurally unique BSTs for n keys is equivalent to the n-th Catalan number, which can be computed using known formulas or dynamic programming.
Approach:
The idea is to construct all possible BSTs by considering each number from 1 to n as the root and recursively constructing the left and right subtrees. For each root i, all numbers from 1 to i-1 will form the left subtree, and numbers from i+1 to n will form the right subtree. We recursively generate all possible BSTs for the left and right subtrees and then combine each left subtree with each right subtree for the current root.
Follow the steps below to solve the problem:
- Initialize a array of BSTs as empty.
- For every number i from 1 to n, do the following:
- Create a new node with key i, let this node be 'node'.
- Recursively construct a list of all possible left subtrees from numbers 1 to i-1.
- Recursively construct a list of all possible right subtrees from numbers i+1 to n.
- Iterate over all possible left subtrees:
- For each current left subtree, iterate over all possible right subtrees.
- Attach the current left and right subtrees to 'node'.
- Add the node (with attached subtrees) to the list of BSTs.
Below is the implementation of the above approach:
C++
// C++ program to find all binary trees
// from 1 to n
#include <bits/stdc++.h>
using namespace std;
class Node {
public:
int data;
Node* left;
Node* right;
Node(int x) {
data = x;
left = right = nullptr;
}
};
// Function to construct all possible binary trees
vector<Node*> getTrees(int start, int end) {
vector<Node*> trees;
// Base case: If start index is greater than end,
// return empty tree (nullptr)
if (start > end) {
trees.push_back(nullptr);
return trees;
}
// Iterate through all values in the array
// and construct left and right subtrees
for (int i = start; i <= end; ++i) {
// Generate all left subtrees
vector<Node*> leftTrees = getTrees(start, i - 1);
// Generate all right subtrees
vector<Node*> rightTrees = getTrees(i + 1, end);
// Combine each left and right subtree with
// the current root
for (Node* left : leftTrees) {
for (Node* right : rightTrees) {
// Make i as root
Node* root = new Node(i);
root->left = left;
root->right = right;
// Add the constructed tree to the list of trees
trees.push_back(root);
}
}
}
return trees;
}
void preorder(Node* root) {
if (root != nullptr) {
cout << root->data << " ";
preorder(root->left);
preorder(root->right);
}
}
int main() {
vector<Node*> trees = getTrees(1, 3);
for (int i = 0; i < trees.size(); ++i) {
preorder(trees[i]);
cout << "\n";
}
return 0;
}
Java
// Java program to find all binary
// trees from 1 to n
import java.util.ArrayList;
import java.util.List;
class Node {
int data;
Node left, right;
Node(int data) {
this.data = data;
left = right = null;
}
}
class GfG {
// Function to construct all possible binary trees
static List<Node> getTrees(int start, int end) {
List<Node> trees = new ArrayList<>();
// Base case: If start index is greater than end,
// return empty tree (null)
if (start > end) {
trees.add(null);
return trees;
}
// Iterate through all values in the array and
// construct left and right subtrees
for (int i = start; i <= end; i++) {
// Generate all left subtrees
List<Node> leftTrees = getTrees(start, i - 1);
// Generate all right subtrees
List<Node> rightTrees = getTrees(i + 1, end);
// Combine each left and right
// subtree with the current root
for (Node left : leftTrees) {
for (Node right : rightTrees) {
// Make i as root
Node root = new Node(i);
root.left = left;
root.right = right;
// Add the constructed tree to the
// list of trees
trees.add(root);
}
}
}
return trees;
}
static void preorder(Node root) {
if (root != null) {
System.out.print(root.data + " ");
preorder(root.left);
preorder(root.right);
}
}
public static void main(String[] args) {
List<Node> trees = getTrees(1, 3);
for (Node tree : trees) {
preorder(tree);
System.out.println();
}
}
}
Python
# Python program to find all binary
# trees from 1 to n
class Node:
def __init__(self, data):
self.data = data
self.left = None
self.right = None
# Function to construct all possible
# binary trees
def get_trees(start, end):
trees = []
# Base case: If start index is greater than end,
# return empty tree (None)
if start > end:
trees.append(None)
return trees
# Iterate through all values in the array and
# construct left and right subtrees
for i in range(start, end + 1):
# Generate all left subtrees
left_trees = get_trees(start, i - 1)
# Generate all right subtrees
right_trees = get_trees(i + 1, end)
# Combine each left and right subtree
# with the current root
for left in left_trees:
for right in right_trees:
# Make i as root
root = Node(i)
root.left = left
root.right = right
# Add the constructed tree to
# the list of trees
trees.append(root)
return trees
def preorder(root):
if root is not None:
print(root.data, end=" ")
preorder(root.left)
preorder(root.right)
if __name__ == "__main__":
trees = get_trees(1, 3)
for tree in trees:
preorder(tree)
print()
C#
// C# program to find all binary trees
// from 1 to n
using System;
using System.Collections.Generic;
class Node {
public int data;
public Node left, right;
public Node(int data) {
this.data = data;
this.left = this.right = null;
}
}
class GfG {
// Function to construct all possible binary trees
static List<Node> GetTrees(int start, int end) {
List<Node> trees = new List<Node>();
// Base case: If start index is greater than end,
// return empty tree (null)
if (start > end) {
trees.Add(null);
return trees;
}
// Iterate through all values in the array and
// construct left and right subtrees
for (int i = start; i <= end; i++) {
// Generate all left subtrees
List<Node> leftTrees = GetTrees(start, i - 1);
// Generate all right subtrees
List<Node> rightTrees = GetTrees(i + 1, end);
// Combine each left and right subtree
// with the current root
foreach (Node left in leftTrees) {
foreach (Node right in rightTrees) {
// Make i as root
Node root = new Node(i);
root.left = left;
root.right = right;
// Add the constructed tree to
// the list of trees
trees.Add(root);
}
}
}
return trees;
}
static void Preorder(Node root) {
if (root != null) {
Console.Write(root.data + " ");
Preorder(root.left);
Preorder(root.right);
}
}
static void Main(string[] args) {
List<Node> trees = GetTrees(1, 3);
foreach (Node tree in trees) {
Preorder(tree);
Console.WriteLine();
}
}
}
JavaScript
// JavaScript program to find all binary
// trees from 1 to n
class Node {
constructor(data) {
this.data = data;
this.left = null;
this.right = null;
}
}
// Function to construct all possible binary trees
function getTrees(start, end) {
const trees = [];
// Base case: If start index is greater than end,
// return empty tree (null)
if (start > end) {
trees.push(null);
return trees;
}
// Iterate through all values in the array
// and construct left and right subtrees
for (let i = start; i <= end; i++) {
// Generate all left subtrees
const leftTrees = getTrees(start, i - 1);
// Generate all right subtrees
const rightTrees = getTrees(i + 1, end);
// Combine each left and right subtree
// with the current root
leftTrees.forEach(left => {
rightTrees.forEach(right => {
// Make i as root
const root = new Node(i);
root.left = left;
root.right = right;
// Add the constructed tree to
// the list of trees
trees.push(root);
});
});
}
return trees;
}
function preorder(root) {
if (root !== null) {
process.stdout.write(root.data + " ");
preorder(root.left);
preorder(root.right);
}
}
const trees = getTrees(1, 3);
trees.forEach(tree => {
preorder(tree);
console.log();
});
Output1 2 3
1 3 2
2 1 3
3 1 2
3 2 1
Time Complexity: O(Cn * n), where Cn is the Catalan number
Auxiliary Space: O(Cn * n), for storing all possible trees and the space used by the recursion stack.
Related Articles
Explore
DSA Fundamentals
Data Structures
Algorithms
Advanced
Interview Preparation
Practice Problem