In this article, first count of possible BST (Binary Search Trees)s is discussed, then the construction of all possible BSTs.
How many structurally unique BSTs for keys from 1..N?
For example, for N = 2, there are 2 unique BSTs
1 2
\ /
2 1
For N = 3, there are 5 possible BSTs
1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
We strongly recommend you to minimize your browser and try this yourself first.
We know that all node in left subtree are smaller than root and in right subtree are larger than root so if we have ith number as root, all numbers from 1 to i-1 will be in left subtree and i+1 to N will be in right subtree. If 1 to i-1 can form x different trees and i+1 to N can from y different trees then we will have x*y total trees when ith number is root and we also have N choices for root also so we can simply iterate from 1 to N for root and another loop for left and right subtree. If we take a closer look, we can notice that the count is basically n’th Catalan number. We have discussed different approaches to find n’th Catalan number here.
How to construct all BST for keys 1..N?
The idea is to maintain a list of roots of all BSTs. Recursively construct all possible left and right subtrees. Create a tree for every pair of left and right subtree and add the tree to list. Below is detailed algorithm.
- Initialize list of BSTs as empty.
- For every number i where i varies from 1 to N, do following
- Create a new node with key as ‘i’, let this node be ‘node’
- Recursively construct list of all left subtrees.
- Recursively construct list of all right subtrees.
- Iterate for all left subtrees
- For current leftsubtree, iterate for all right subtrees
- Add current left and right subtrees to ‘node’ and add
- node’ to list.
Below is the implementation of the above idea.
C++
#include <bits/stdc++.h>
using namespace std;
struct node
{
int key;
struct node *left, *right;
};
struct node *newNode( int item)
{
struct node *temp = new node;
temp->key = item;
temp->left = temp->right = NULL;
return temp;
}
void preorder( struct node *root)
{
if (root != NULL)
{
cout << root->key << " " ;
preorder(root->left);
preorder(root->right);
}
}
vector< struct node *> constructTrees( int start, int end)
{
vector< struct node *> list;
if (start > end)
{
list.push_back(NULL);
return list;
}
for ( int i = start; i <= end; i++)
{
vector< struct node *> leftSubtree = constructTrees(start, i - 1);
vector< struct node *> rightSubtree = constructTrees(i + 1, end);
for ( int j = 0; j < leftSubtree.size(); j++)
{
struct node* left = leftSubtree[j];
for ( int k = 0; k < rightSubtree.size(); k++)
{
struct node * right = rightSubtree[k];
struct node * node = newNode(i);
node->left = left;
node->right = right;
list.push_back(node);
}
}
}
return list;
}
int main()
{
vector< struct node *> totalTreesFrom1toN = constructTrees(1, 3);
cout << "Preorder traversals of all constructed BSTs are \n" ;
for ( int i = 0; i < totalTreesFrom1toN.size(); i++)
{
preorder(totalTreesFrom1toN[i]);
cout << endl;
}
return 0;
}
|
Java
import java.util.ArrayList;
public class Main {
static ArrayList<Node> constructTrees( int start, int end)
{
ArrayList<Node> list= new ArrayList<>();
if (start > end)
{
list.add( null );
return list;
}
for ( int i = start; i <= end; i++)
{
ArrayList<Node> leftSubtree = constructTrees(start, i - 1 );
ArrayList<Node> rightSubtree = constructTrees(i + 1 , end);
for ( int j = 0 ; j < leftSubtree.size(); j++)
{
Node left = leftSubtree.get(j);
for ( int k = 0 ; k < rightSubtree.size(); k++)
{
Node right = rightSubtree.get(k);
Node node = new Node(i);
node.left = left;
node.right = right;
list.add(node);
}
}
}
return list;
}
static void preorder(Node root)
{
if (root != null )
{
System.out.print(root.key+ " " ) ;
preorder(root.left);
preorder(root.right);
}
}
public static void main(String args[])
{
ArrayList<Node> totalTreesFrom1toN = constructTrees( 1 , 3 );
System.out.println( "Preorder traversals of all constructed BSTs are " );
for ( int i = 0 ; i < totalTreesFrom1toN.size(); i++)
{
preorder(totalTreesFrom1toN.get(i));
System.out.println();
}
}
}
class Node
{
int key;
Node left, right;
Node( int data)
{
this .key=data;
left=right= null ;
}
};
|
Python3
class newNode:
def __init__( self , item):
self .key = item
self .left = None
self .right = None
def preorder(root) :
if (root ! = None ) :
print (root.key, end = " " )
preorder(root.left)
preorder(root.right)
def constructTrees(start, end):
list = []
if (start > end) :
list .append( None )
return list
for i in range (start, end + 1 ):
leftSubtree = constructTrees(start, i - 1 )
rightSubtree = constructTrees(i + 1 , end)
for j in range ( len (leftSubtree)) :
left = leftSubtree[j]
for k in range ( len (rightSubtree)):
right = rightSubtree[k]
node = newNode(i)
node.left = left
node.right = right
list .append(node)
return list
if __name__ = = '__main__' :
totalTreesFrom1toN = constructTrees( 1 , 3 )
print ( "Preorder traversals of all" ,
"constructed BSTs are" )
for i in range ( len (totalTreesFrom1toN)):
preorder(totalTreesFrom1toN[i])
print ()
|
C#
using System.Collections;
using System;
class GFG
{
static ArrayList constructTrees( int start, int end)
{
ArrayList list = new ArrayList();
if (start > end)
{
list.Add( null );
return list;
}
for ( int i = start; i <= end; i++)
{
ArrayList leftSubtree = constructTrees(start, i - 1);
ArrayList rightSubtree = constructTrees(i + 1, end);
for ( int j = 0; j < leftSubtree.Count; j++)
{
Node left = (Node)leftSubtree[j];
for ( int k = 0; k < rightSubtree.Count; k++)
{
Node right = (Node)rightSubtree[k];
Node node = new Node(i);
node.left = left;
node.right = right;
list.Add(node);
}
}
}
return list;
}
static void preorder(Node root)
{
if (root != null )
{
Console.Write(root.key+ " " ) ;
preorder(root.left);
preorder(root.right);
}
}
public static void Main(String []args)
{
ArrayList totalTreesFrom1toN = constructTrees(1, 3);
Console.WriteLine( "Preorder traversals of all" +
"constructed BSTs are " );
for ( int i = 0; i < totalTreesFrom1toN.Count; i++)
{
preorder((Node)totalTreesFrom1toN[i]);
Console.WriteLine();
}
}
public class Node
{
public int key;
public Node left, right;
public Node( int data)
{
this .key=data;
left=right= null ;
}
};
}
|
Javascript
<script>
class Node
{
constructor(data)
{
this .key = data;
this .left = null ;
this .right = null ;
}
};
function constructTrees(start, end)
{
var list = [];
if (start > end)
{
list.push( null );
return list;
}
for ( var i = start; i <= end; i++)
{
var leftSubtree = constructTrees(start, i - 1);
var rightSubtree = constructTrees(i + 1, end);
for ( var j = 0; j < leftSubtree.length; j++)
{
var left = leftSubtree[j];
for ( var k = 0; k < rightSubtree.length; k++)
{
var right = rightSubtree[k];
var node = new Node(i);
node.left = left;
node.right = right;
list.push(node);
}
}
}
return list;
}
function preorder(root)
{
if (root != null )
{
document.write(root.key+ " " ) ;
preorder(root.left);
preorder(root.right);
}
}
var totalTreesFrom1toN = constructTrees(1, 3);
document.write( "Preorder traversals of all" +
"constructed BSTs are<br>" );
for ( var i = 0; i < totalTreesFrom1toN.length; i++)
{
preorder(totalTreesFrom1toN[i]);
document.write( "<br>" );
}
</script>
|
OutputPreorder traversals of all constructed BSTs are
1 2 3
1 3 2
2 1 3
3 1 2
3 2 1
Time Complexity: O(2^n).
The time complexity of this solution is exponential. This is because we are constructing all possible BSTs. Since at each level, we are generating two subproblems and at each level, there are O(2^n) subproblems, the time complexity is O(2^n).
Auxiliary Space: O(2^n).
The space complexity of this solution is also exponential. This is because we are constructing all possible BSTs. Since at each level, we are generating two subproblems and at each level, there are O(2^n) subproblems, the space complexity is O(2^n).
This article is contributed by Utkarsh Trivedi. Please write comments if you find anything incorrect, or if you want to share more information about the topic discussed above.