[Naive Approach] Generate All Unique BSTs - O(Cn à n) Time and O(Cn à n) Space
The idea is to recursively try every node as the root. For each root, recursively count the number of BSTs that can be formed by the left and right subtrees, multiply these counts, and add the results for all possible roots.
Working of Approach:
Recursively choose every node from 1 to n as the root of the BST.
For each root, recursively count the number of BSTs that can be formed by the left and right subtrees.
Multiply the counts of the left and right subtrees and add the result to the answer.
After considering all possible roots, return the total number of unique BSTs.
C++
#include<iostream>usingnamespacestd;// Function to return the total number of possible unique BSTs.intnumTrees(intn){// Base caseif(n<=1)return1;intans=0;// Try every node as the root.for(introot=1;root<=n;root++){// Count BSTs formed by the left and right subtrees.ans+=numTrees(root-1)*numTrees(n-root);}// Return the total number of unique BSTs.returnans;}intmain(){intn=3;cout<<numTrees(n);return0;}
Java
publicclassGFG{// Function to return the total number of possible// unique BSTs.staticintnumTrees(intn){// Base caseif(n<=1)return1;intans=0;// Try every node as the root.for(introot=1;root<=n;root++){// Count BSTs formed by the left and right// subtrees.ans+=numTrees(root-1)*numTrees(n-root);}// Return the total number of unique BSTs.returnans;}publicstaticvoidmain(String[]args){intn=3;System.out.print(numTrees(n));}}
Python
# Function to return the total number of possible unique BSTs.defnumTrees(n):# Base caseifn<=1:return1ans=0# Try every node as the root.forrootinrange(1,n+1):# Count BSTs formed by the left and right subtrees.ans+=numTrees(root-1)*numTrees(n-root)# Return the total number of unique BSTs.returnansif__name__=='__main__':n=3print(numTrees(n))
C#
usingSystem;classGFG{// Function to return the total number of possible// unique BSTs.staticintnumTrees(intn){// Base caseif(n<=1)return1;intans=0;// Try every node as the root.for(introot=1;root<=n;root++){// Count BSTs formed by the left and right// subtrees.ans+=numTrees(root-1)*numTrees(n-root);}// Return the total number of unique BSTs.returnans;}staticvoidMain(){intn=3;Console.Write(numTrees(n));}}
JavaScript
// Function to return the total number of possible unique// BSTs.functionnumTrees(n){// Base caseif(n<=1)return1;letans=0;// Try every node as the root.for(letroot=1;root<=n;root++){// Count BSTs formed by the left and right subtrees.ans+=numTrees(root-1)*numTrees(n-root);}// Return the total number of unique BSTs.returnans;}// Driver Codeletn=3;console.log(numTrees(n));
Output
5
[Expected Approach] Using Dynamic Programming (Tabulation) - O(n ^ 2) Time and O(n) Space
The idea is to use Dynamic Programming (Tabulation) where dp[i] stores the number of unique BSTs that can be formed using i nodes. For each possible root, multiply the number of BSTs that can be formed by the left and right subtrees, and add the result to dp[i]. Fill the dp array iteratively from 0 to n, and return dp[n].
Working of Approach:
Create a dp array where dp[i] stores the number of unique BSTs that can be formed using i nodes.
Initialize the base cases: dp[0] = 1 and dp[1] = 1, as there is exactly one BST with 0 or 1 node.
For each number of nodes from 2 to n, try every node as the root, multiply the number of possible left and right subtrees, and add the result to dp[i].
After filling the dp array, return dp[n], which represents the total number of structurally unique BSTs that can be formed using n nodes.
Let us understand with an example: Input: n = 3
Initialize dp[0] = 1 and dp[1] = 1, representing the number of unique BSTs with 0 and 1 node.
For i = 2, choose each node as the root: dp[2] = dp[0] Ã dp[1] + dp[1] Ã dp[0] = 1 + 1 = 2.
Store each computed value in the dp array and use it for subsequent calculations.
Finally, return dp[3] = 5, which is the total number of structurally unique BSTs that can be formed using 3 nodes.
C++
#include<iostream>usingnamespacestd;// Function to return the total number of possible unique BSTs.intnumTrees(intn){// dp[i] stores the number of unique BSTs// that can be formed using i nodes.intdp[n+1];// Base cases.dp[0]=1;dp[1]=1;// Fill the dp[] array in a bottom-up manner.for(inti=2;i<=n;i++){dp[i]=0;// Try every node as the root.for(intj=1;j<=i;j++){// If j is chosen as the root, then// nodes [1...j-1] form the left subtree and// nodes [j+1...i] form the right subtree.// Multiply the number of possible left and// right subtrees and add it to dp[i].dp[i]+=dp[j-1]*dp[i-j];}}// Return the total number of unique BSTs.returndp[n];}intmain(){intn=3;cout<<numTrees(n);return0;}
Java
publicclassGFG{// Function to return the total number of possible// unique BSTs.staticintnumTrees(intn){// dp[i] stores the number of unique BSTs// that can be formed using i nodes.int[]dp=newint[n+1];// Base cases.dp[0]=1;dp[1]=1;// Fill the dp[] array in a bottom-up manner.for(inti=2;i<=n;i++){dp[i]=0;// Try every node as the root.for(intj=1;j<=i;j++){// If j is chosen as the root, then// nodes [1...j-1] form the left subtree and// nodes [j+1...i] form the right subtree.// Multiply the number of possible left and// right subtrees and add it to dp[i].dp[i]+=dp[j-1]*dp[i-j];}}// Return the total number of unique BSTs.returndp[n];}publicstaticvoidmain(String[]args){intn=3;System.out.print(numTrees(n));}}
Python
# Function to return the total number of possible unique BSTs.defnumTrees(n):# dp[i] stores the number of unique BSTs# that can be formed using i nodes.dp=[0]*(n+1)# Base cases.dp[0]=1dp[1]=1# Fill the dp[] array in a bottom-up manner.foriinrange(2,n+1):dp[i]=0# Try every node as the root.forjinrange(1,i+1):# If j is chosen as the root, then# nodes [1...j-1] form the left subtree and# nodes [j+1...i] form the right subtree.# Multiply the number of possible left and# right subtrees and add it to dp[i].dp[i]+=dp[j-1]*dp[i-j]# Return the total number of unique BSTs.returndp[n]if__name__=='__main__':n=3print(numTrees(n))
C#
usingSystem;classGFG{// Function to return the total number of possible// unique BSTs.staticintnumTrees(intn){// dp[i] stores the number of unique BSTs// that can be formed using i nodes.int[]dp=newint[n+1];// Base cases.dp[0]=1;dp[1]=1;// Fill the dp[] array in a bottom-up manner.for(inti=2;i<=n;i++){dp[i]=0;// Try every node as the root.for(intj=1;j<=i;j++){// If j is chosen as the root, then// nodes [1...j-1] form the left subtree and// nodes [j+1...i] form the right subtree.// Multiply the number of possible left and// right subtrees and add it to dp[i].dp[i]+=dp[j-1]*dp[i-j];}}// Return the total number of unique BSTs.returndp[n];}staticvoidMain(){intn=3;Console.Write(numTrees(n));}}
JavaScript
// Function to return the total number of possible unique// BSTs.functionnumTrees(n){// dp[i] stores the number of unique BSTs// that can be formed using i nodes.letdp=newArray(n+1).fill(0);// Base cases.dp[0]=1;dp[1]=1;// Fill the dp[] array in a bottom-up manner.for(leti=2;i<=n;i++){dp[i]=0;// Try every node as the root.for(letj=1;j<=i;j++){// If j is chosen as the root, then// nodes [1...j-1] form the left subtree and// nodes [j+1...i] form the right subtree.// Multiply the number of possible left and// right subtrees and add it to dp[i].dp[i]+=dp[j-1]*dp[i-j];}}// Return the total number of unique BSTs.returndp[n];}letn=3;console.log(numTrees(n));