Unique Binary Search Trees

To solve this coding challenge, we need to determine the number of structurally unique Binary Search Trees (BSTs) that can be formed using
n
nodes, where the nodes have unique values from 1 to
n
. The solution involves dynamic programming, which is a method for solving a complex problem by breaking it down into simpler subproblems and storing the results of these subproblems to avoid redundant calculations.

Explanation

  1. Understanding the BST : A Binary Search Tree (BST) is a tree structure where each node has at most two children. The left child contains nodes with values less than the parent node, and the right child contains nodes with values greater than the parent node.
  2. Unique BSTs : For each node
    i
    from 1 to
    n
    , we can consider it as the root of the tree. The number of unique BSTs with
    i
    as the root is the product of the number of unique BSTs possible with the left children (nodes 1 to
    i-1
    ) and the number of unique BSTs possible with the right children (nodes
    i+1
    to
    n
    ).
  3. Dynamic Programming Approach :
    • We use a list
      dp
      where
      dp[i]
      represents the number of unique BSTs that can be constructed with
      i
      nodes.
    • Initialize
      dp[0]
      and
      dp[1]
      to 1 since there is exactly one BST with
      0
      nodes (an empty tree) and one BST with
      1
      node.
    • For
      i
      from 2 to
      n
      :
      • For each
        j
        from 1 to
        i
        :
        • Compute the number of unique BSTs for
          i
          nodes by considering
          j
          as the root.
        • The left subtree will have
          j-1
          nodes, and the right subtree will have
          i-j
          nodes.
        • Update
          dp[i]
          by adding the product of the number of unique BSTs for the left and right subtrees.
  4. Result : The result
    dp[n]
    will give the number of unique BSTs that can be formed with
    n
    nodes.
  5. Step-by-Step Explanation

    Initialization:
  6. Initialize a list
    dp
    of size
    n+1
    with all elements set to 0.
  7. Set
    dp[0]
    and
    dp[1]
    to 1, as there is one unique BST for 0 and 1 node respectively.
  8. DP Iteration:
  9. Loop through
    i
    from 2 to
    n
    :
    • For each
      i
      , loop through
      j
      from 1 to
      i
      :
      • Calculate the number of trees with
        i
        nodes by considering each
        j
        as the root.
      • Use the formula
        dp[i] += dp[j-1] * dp[i-j]
        to accumulate the count.
    Result:
  10. Return
    dp[n]
    which contains the number of unique BSTs for
    n
    nodes.

Pseudocode:

                                            
# Initialize the dp array with zeros and length n+1
dp = [0] * (n + 1)

# The number of BSTs with 0 or 1 node is 1
dp[0] = dp[1] = 1

# Start filling the dp array for i from 2 to n
for i in range(2, n + 1):
    
    # For each number of nodes i, calculate the number of unique BSTs
    for j in range(1, i + 1):
        
        # dp[j-1] represents the number of unique BSTs with j-1 nodes (left subtree)
        # dp[i-j] represents the number of unique BSTs with i-j nodes (right subtree)
        dp[i] += dp[j - 1] * dp[i - j]

# Return the result stored in dp[n] which is the number of unique BSTs with n nodes
return dp[n]

                                        
The above pseudocode provides a method to calculate the number of unique BSTs using dynamic programming. It iterates over possible root nodes and combines the counts of unique BSTs for left and right subtrees. By storing intermediate results in the
dp
array, this method efficiently computes the desired result without redundant calculations.