Given an integer N, the task is to count the number of possible Binary Search Trees with N keys.
Examples:
Input: N = 2 Output: 2 For N = 2, there are 2 unique BSTs 1 2 \ / 2 1 Input: N = 9 Output: 4862
Approach: The number of binary search trees that will be formed with N keys can be calculated by simply evaluating the corresponding number in Catalan Number series.
First few Catalan numbers for n = 0, 1, 2, 3, … are 1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, …
Catalan numbers satisfy the following recursive formula:
Below is the implementation of the above approach:
// C++ implementation of the approach #include <iostream> using namespace std;
// Function to return the count // of unique BSTs with n keys int uniqueBSTs( int n)
{ int n1, n2, sum = 0;
// Base cases
if (n == 1 || n == 0)
return 1;
// Find the nth Catalan number
for ( int i = 1; i <= n; i++) {
// Recursive calls
n1 = uniqueBSTs(i - 1);
n2 = uniqueBSTs(n - i);
sum += n1 * n2;
}
// Return the nth Catalan number
return sum;
} // Driver code int main()
{ int n = 2;
// Function call
cout << uniqueBSTs(n);
return 0;
} |
// Java implementation of the approach import java.io.*;
class GFG {
// Function to return the count
// of unique BSTs with n keys
static int uniqueBSTs( int n)
{
int n1, n2, sum = 0 ;
// Base cases
if (n == 1 || n == 0 )
return 1 ;
// Find the nth Catalan number
for ( int i = 1 ; i <= n; i++) {
// Recursive calls
n1 = uniqueBSTs(i - 1 );
n2 = uniqueBSTs(n - i);
sum += n1 * n2;
}
// Return the nth Catalan number
return sum;
}
// Driver code
public static void main(String[] args)
{
int n = 2 ;
// Function call
System.out.println(uniqueBSTs(n));
}
} // This code is contributed by jit_t. |
# Python3 implementation of the approach # Function to return the count # of unique BSTs with n keys def uniqueBSTs(n):
n1, n2, sum = 0 , 0 , 0
# Base cases
if (n = = 1 or n = = 0 ):
return 1
# Find the nth Catalan number
for i in range ( 1 , n + 1 ):
# Recursive calls
n1 = uniqueBSTs(i - 1 )
n2 = uniqueBSTs(n - i)
sum + = n1 * n2
# Return the nth Catalan number
return sum
# Driver code n = 2
# Function call print (uniqueBSTs(n))
# This code is contributed by Mohit Kumar |
// C# implementation of the approach using System;
class GFG {
// Function to return the count
// of unique BSTs with n keys
static int uniqueBSTs( int n)
{
int n1, n2, sum = 0;
// Base cases
if (n == 1 || n == 0)
return 1;
// Find the nth Catalan number
for ( int i = 1; i <= n; i++)
{
// Recursive calls
n1 = uniqueBSTs(i - 1);
n2 = uniqueBSTs(n - i);
sum += n1 * n2;
}
// Return the nth Catalan number
return sum;
}
// Driver code
static public void Main()
{
int n = 2;
// Function call
Console.WriteLine(uniqueBSTs(n));
}
} // This code is contributed by ajit. |
<script> // Javascript implementation of the approach
// Function to return the count
// of unique BSTs with n keys
function uniqueBSTs(n)
{
let n1, n2, sum = 0;
// Base cases
if (n == 1 || n == 0)
return 1;
// Find the nth Catalan number
for (let i = 1; i <= n; i++)
{
// Recursive calls
n1 = uniqueBSTs(i - 1);
n2 = uniqueBSTs(n - i);
sum += n1 * n2;
}
// Return the nth Catalan number
return sum;
}
let n = 2;
// Function call
document.write(uniqueBSTs(n));
</script> |
Output
2
The problem can be solved in a dynamic programming way.
Here is a snippet of how the recurrence tree will proceed:
G(4) / | | \ G(0)G(3) G(1)G(2) G(2)G(1) G(3)G(0) / | \ G(0)G(2) G(1)G(1) G(2)G(0) / \ G(0)G(1) G(1)G(0) // base case
Note: Without memoization, the time complexity is upper bounded by O(N x N!).
Given a sequence 1…n, to construct a Binary Search Tree (BST) out of the sequence, we could enumerate each number i in the sequence, and use the number as the root, naturally, the subsequence 1…(i-1) on its left side would lay on the left branch of the root, and similarly the right subsequence (i+1)…n lay on the right branch of the root. We then can construct the subtree from the subsequence recursively. Through the above approach, we could ensure that the BST that we construct is all unique since they have unique roots.
The problem is to calculate the number of unique BST. To do so, we need to define two functions:
1.G(n): the number of unique BST for a sequence of length n. 2.F(i, n), 1 <= i <= n: The number of unique BST, where the number i is the root of BST, and the sequence ranges from 1 to n. As one can see, G(n) is the actual function we need to calculate in order to solve the problem. And G(n) can be derived from F(i, n), which at the end, would recursively refer to G(n). First of all, given the above definitions, we can see that the total number of unique BST G(n), is the sum of BST F(i) using each number i as a root. i.e., G(n) = F(1, n) + F(2, n) + ... + F(n, n). Given a sequence 1…n, we pick a number i out of the sequence as the root, then the number of unique BST with the specified root F(i), is the cartesian product of the number of BST for its left and right subtrees.For example, F(2, 4): the number of unique BST tree with number 2 as its root. To construct an unique BST out of the entire sequence [1, 2, 3, 4] with 2 as the root, which is to say, we need to construct an unique BST out of its left subsequence [1] and another BST out of the right subsequence [3,4], and then combine them together (i.e. cartesian product). F(i, n) = G(i-1) * G(n-i) 1 <= i <= n Combining the above two formulas, we obtain the recursive formula for G(n). i.e. G(n) = G(0) * G(n-1) + G(1) * G(n-2) + … + G(n-1) * G(0)
In terms of calculation, we need to start with the lower number, since the value of G(n)
depends on the values of G(0) … G(n-1).
Below is the above implementation of the above algorithm:
// C++ dynamic programming implementation of the approach #include <iostream> using namespace std;
// Function to return the count // of unique BSTs with n keys int uniqueBSTs( int n)
{ // construct a dp array to store the
// subsequent results
int dparray[n + 1] = { 0 };
// there is only one combination to construct a
// BST out of a sequence of
dparray[0] = dparray[1] = 1;
// length 1 (only a root) or 0 (empty tree).
for ( int i = 2; i <= n; ++i)
{
// choosing every value as root
for ( int k = 1; k <= i; ++k)
{
dparray[i] += dparray[k - 1] * dparray[i - k];
}
}
return dparray[n];
} // Driver code int main()
{ int n = 2;
// Function call
cout << uniqueBSTs(n);
return 0;
} |
// Java dynamic programming implementation of the approach import java.io.*;
import java.util.*;
class GFG
{ // Function to return the count
// of unique BSTs with n keys
static int uniqueBSTs( int n)
{
// construct a dp array to store the
// subsequent results
int [] dparray = new int [n + 1 ];
Arrays.fill(dparray, 0 );
// there is only one combination to construct a
// BST out of a sequence of
dparray[ 0 ] = dparray[ 1 ] = 1 ;
// length 1 (only a root) or 0 (empty tree).
for ( int i = 2 ; i <= n; ++i)
{
// choosing every value as root
for ( int k = 1 ; k <= i; ++k)
{
dparray[i] += dparray[k - 1 ] * dparray[i - k];
}
}
return dparray[n];
}
// Driver code
public static void main (String[] args)
{
int n = 2 ;
// Function call
System.out.println(uniqueBSTs(n));
}
} // This code is contributed by avanitrachhadiya2155 |
# Python3 dynamic programming # implementation of the approach # Function to return the count # of unique BSTs with n keys def uniqueBSTs(n):
# Construct a dp array to store the
# subsequent results
dparray = [ 0 for i in range (n + 1 )]
# There is only one combination to
# construct a BST out of a sequence of
dparray[ 0 ] = 1
dparray[ 1 ] = 1
# length 1 (only a root) or 0 (empty tree).
for i in range ( 2 , n + 1 , 1 ):
# Choosing every value as root
for k in range ( 1 , i + 1 , 1 ):
dparray[i] + = (dparray[k - 1 ] *
dparray[i - k])
return dparray[n]
# Driver code if __name__ = = '__main__' :
n = 2
# Function call
print (uniqueBSTs(n))
# This code is contributed by bgangwar59 |
// C# dynamic programming implementation // of the approach using System;
class GFG{
// Function to return the count // of unique BSTs with n keys static int uniqueBSTs( int n)
{ // construct a dp array to store the
// subsequent results
int [] dparray = new int [n + 1];
// there is only one combination to
// construct a BST out of a sequence of
dparray[0] = dparray[1] = 1;
// length 1 (only a root) or 0 (empty tree).
for ( int i = 2; i <= n; ++i)
{
// Choosing every value as root
for ( int k = 1; k <= i; ++k)
{
dparray[i] += dparray[k - 1] *
dparray[i - k];
}
}
return dparray[n];
} // Driver code public static void Main(String[] args)
{ int n = 2;
// Function call
Console.WriteLine(uniqueBSTs(n));
} } // This code is contributed by Amit Katiyar |
<script> // Javascript dynamic programming
// implementation of the approach
// Function to return the count
// of unique BSTs with n keys
function uniqueBSTs(n)
{
// construct a dp array to store the
// subsequent results
let dparray = new Array(n + 1);
dparray.fill(0);
// there is only one combination to construct a
// BST out of a sequence of
dparray[0] = dparray[1] = 1;
// length 1 (only a root) or 0 (empty tree).
for (let i = 2; i <= n; ++i)
{
// choosing every value as root
for (let k = 1; k <= i; ++k)
{
dparray[i] += dparray[k - 1] * dparray[i - k];
}
}
return dparray[n];
}
let n = 2;
// Function call
document.write(uniqueBSTs(n));
</script> |
Output
2
Time Complexity: O(N2)
Space Complexity: O(N)
In this post, we will discuss an O(n) and an O(1) space solution based on Dynamic Programming.
We know that the formula for Catalan number for a variable n is
Similarly Catalan number for (n-1) nodes =
The formula for n nodes can be rewritten as
= Catalan number for (n-1) nodes*
So for every iteration for ‘i’ going from 1 to n we will store catalan number for ‘i-1’ nodes and compute for ith node.
Below is the implementation for the above approach:
#include <bits/stdc++.h> using namespace std;
// Function to find number of unique BST int numberOfBST( int n)
{ // For n=1 answer is 1
long v = 1;
for ( int i = 2; i <= n; i++) {
// using previous answer in v to calculate current
// catalan number.
v = ((v * (i * 2) * (i * 2 - 1)) / ((i + 1) * (i)));
}
return v;
} int main()
{ int n = 4;
cout << "Number of Unique BST for " << n << " nodes is "
<< numberOfBST(n) << endl;
return 0;
} |
class GFG{
// Function to find number of unique BST static long numberOfBST( int n)
{ // For n=1 answer is 1
long v = 1 ;
for ( int i = 2 ; i <= n; i++)
{
// Using previous answer in v to calculate
// current catalan number.
v = ((v * (i * 2 ) * (i * 2 - 1 )) /
((i + 1 ) * (i)));
}
return v;
} // Driver code public static void main(String[] args)
{ int n = 4 ;
System.out.print( "Number of Unique BST for " + n +
" nodes is " + numberOfBST(n) + "\n" );
} } // This code is contributed by shikhasingrajput |
# Function to find number of unique BST def numberOfBST(n):
# For n=1 answer is 1
v = 1
for i in range ( 2 , n + 1 ):
# using previous answer in v to calculate current catalan number.
v = ((v * (i * 2 ) * (i * 2 - 1 )) / ((i + 1 ) * (i)))
return int (v)
n = 4
print ( "Number of Unique BST for" , n, "nodes is" , numberOfBST(n))
# This code is contributed by divyesh072019. |
using System;
class GFG {
// Function to find number of unique BST
static int numberOfBST( int n)
{
// For n=1 answer is 1
int v = 1;
for ( int i = 2; i <= n; i++)
{
// using previous answer in v to calculate current
// catalan number.
v = ((v * (i * 2) * (i * 2 - 1)) / ((i + 1) * (i)));
}
return v;
}
static void Main() {
int n = 4;
Console.Write( "Number of Unique BST for " + n + " nodes is " + numberOfBST(n));
}
} // This code is contributed by rameshtravel07. |
<script> // Function to find number of unique BST
function numberOfBST(n)
{
// For n=1 answer is 1
let v = 1;
for (let i = 2; i <= n; i++) {
// using previous answer in v to calculate current
// catalan number.
v = ((v * (i * 2) * (i * 2 - 1)) / ((i + 1) * (i)));
}
return v;
}
let n = 4;
document.write( "Number of Unique BST for " + n + " nodes is "
+ numberOfBST(n));
// This code is contributed by mukesh07.
</script> |
Output
Number of Unique BST for 4 nodes is 14
Time Complexity: O(n)
Auxiliary Space: O(1).