Unique Binary Search Trees

Updated on 02 July, 2025
Unique Binary Search Trees header image

Problem Statement

The task is to determine the number of unique Binary Search Trees (BST) that can be created using exactly n unique integers ranging from 1 to n. A BST is a special kind of binary tree where each node has at most two children, typically referred to as left child and right child. Each node in a BST must adhere to the properties where all the nodes in the left subtree have values less than the node's value, and all the nodes in the right subtree have values greater than the node's value. The solution should compute how many different structures of BST can be formed using distinct values from 1 to n.

Examples

Example 1

Input:

n = 3

Output:

5

Example 2

Input:

n = 1

Output:

1

Constraints

  • 1 <= n <= 19

Approach and Intuition

To understand how to approach the problem of computing structurally unique BSTs for a given n, we can consider using a dynamic programming approach given the constraint on n (1 ≤ n ≤ 19). Here's an intuitive understanding of solving this problem:

  1. Base Case Consideration:

    • If n = 0 or n = 1, there is only one possible BST, either an empty tree or a tree with one node.
  2. Recursive Formulation:

    • For any number n, consider each integer i from 1 to n as the root of the BST. If i is the root, then:
      • All numbers less than i will form possible BSTs in the left subtree.
      • All numbers greater than i will form possible BSTs in the right subtree.
    • This leads to the understanding that the number of unique BSTs with i as root is the product of the number of unique BSTs possible with i-1 elements (for the left subtree) and n-i elements (for the right subtree).
  3. Dynamic Programming Array:

    • A dynamic programming array dp can be used where dp[k] represents the number of unique BSTs that can be formed using k nodes.
    • Initialize dp[0] to 1 (since there's one empty tree) and iterate through 1 to n to fill the array based on previously computed values.
  4. Iterative Computation:

    • For each value k from 1 to n, iterate through all possible root values. For each root value i, compute the number of left and right subtrees as dp[i-1] and dp[k-i] respectively, and then update the dp[k] as:
      • dp[k] += dp[i-1] * dp[k-i]

By the end of the iterations, dp[n] will give the number of structurally unique BSTs that can be formed with n nodes. This method ensures all possible BST configurations are considered without repetition and computes the result efficiently within the provided constraints.

Solutions

  • C++
  • Java
  • C
  • JavaScript
  • Python
cpp
class Solution {
public:
    int countTrees(int total) {
        long long catalan = 1;
        for (int index = 0; index < total; ++index) {
            catalan = catalan * 2 * (2 * index + 1) / (index + 2);
        }
        return (int)catalan;
    }
};

This solution calculates the number of unique binary search trees possible with total distinct keys using a dynamic programming method derived from the Catalan numbers.

The code is implemented in C++ within a Solution class with a member function named countTrees. The function initializes a long long type variable catalan to 1. This variable is used to store the cumulative result as the Catalan number formula is iteratively applied.

The loop runs from index 0 up to total - 1. In each iteration, the catalan variable is updated based on the classic Catalan number formula: [ \text{catalan} = \text{catalan} \times \frac{2 \times (2 \times \text{index} + 1)}{(\text{index} + 2)} ] This formula progressively computes the count of unique binary search trees by generating each sequence as a product of earlier results.

On completion of the loop, the resultant catalan value holds the count of unique BSTs for the given total. This value is then type-casted to an integer and returned.

This approach ensures efficient computation through directly using the properties of Catalan numbers, which are particularly suited for counting the possible structures of binary search trees.

java
class Solution {
    public int countTrees(int totalNodes) {
        long result = 1;
        for (int index = 0; index < totalNodes; ++index) {
            result = (result * 2 * (2 * index + 1)) / (index + 2);
        }
        return (int) result;
    }
}

The provided Java solution efficiently calculates the number of unique binary search trees (BSTs) that can be formed with totalNodes distinct nodes. This computation is based on the Catalan number, a sequence of natural numbers that have found application in various combinatorial problems, among them the calculation of the possible structures of binary search trees.

Key aspects of the solution include:

  • The method countTrees initiates with a long type variable result set to 1. This choice of data type takes into account the potentially large values of the result due to factorial growth in the formula.

  • A for loop iterates from 0 to totalNodes - 1. Inside the loop, result is updated based on the combinatorial formula for Catalan numbers: result * 2 * (2 * index + 1) / (index + 2). This formula accounts for recursive calculation involving previously computed values, efficiently updating the result without recalculations from scratch.

  • The loop iterates while multiplying the current result with the counted templates and divides by a factor that scales with the loop's index, effectively imitating the recursive property of Catalan numbers.

  • The computed result is cast back to an int when returned, ensuring that the method's output conforms to the expected data type convention.

In summary, apply this method to compute the number of unique BSTs for a given number of distinct nodes, leveraging the mathematical properties of Catalan numbers to ensure efficiency. The implemented approach neatly avoids the overhead and complexity of recursive computations or additional memory usage for dynamic programming approaches.

c
int calculateTrees(int total) {
    long long treesCount = 1;
    for (int index = 0; index < total; ++index) {
        treesCount = treesCount * 2 * (2 * index + 1) / (index + 2);
    }
    return (int)treesCount;
}

The given C function calculateTrees calculates the number of unique binary search trees (BSTs) that can be formed with a specified number of nodes. This computation relies on the Catalan number formula, a sequence of natural numbers that have found applications in various combinatorial structures, including binary trees.

In this function:

  • Initialize a long long variable named treesCount with the value 1 to accommodate the potentially large results due to multiplication.
  • Use a for loop to iterate from 0 to one less than the total number of nodes. During each iteration:
    • Update treesCount with the formula that computes the next Catalan number: ( treesCount = treesCount \times \frac{2 \times (2 \times index + 1)}{index + 2} ). This formula ensures the accurate calculation of the number of unique BSTs for the given node count.
  • Cast treesCount to an int before returning, as the function signature expects an integer return type.

The implementation leverages the properties of the Catalan numbers while ensuring computational efficiency through the use of a single loop and multiplication operations.

js
var calculateTrees = function (count) {
    let result = BigInt(1);
    for (let i = 0; i < count; ++i) {
        result = (result * BigInt(2) * BigInt(2 * i + 1)) / BigInt(i + 2);
    }
    return Number(result);
};

The JavaScript function calculateTrees provided in this solution calculates the number of unique binary search trees that can be formed given count nodes. The function employs dynamic programming principles utilizing a bottom-up approach to solve the problem of counting unique trees.

The solution uses a BigInt data type to handle potential overflow issues due to factorial calculations in larger inputs. The core of the function utilizes a mathematical approach derived from the Catalan number formula to calculate the result. Here's how the function operates:

  • Initialize a result variable as BigInt(1) to start the multiplication process.
  • Loop through numbers from 0 up to but not including the count. In each iteration:
    • Update result with the formula (result * BigInt(2) * BigInt(2 * i + 1)) / BigInt(i + 2). This formula corresponds to a series that defines Catalan numbers, optimizing the calculation needed to count the trees.
  • Once the loop completes, convert the BigInt result back to a standard number using Number(result) and return this value.

The function outputs the number of distinct structures of binary search trees achievable with the number of nodes specified. Given the use of BigInt, this solution is robust even for larger values of count.

python
class Solution(object):
    def countTrees(self, m: int) -> int:
        total = 1
        for j in range(0, m):
            total = total * 2 * (2 * j + 1) / (j + 2)
        return int(total)

The problem "Unique Binary Search Trees" focuses on calculating the number of unique structures of binary search trees that can be formed with m distinct nodes. The provided Python code offers a solution by implementing the Catalan number formula, which is commonly used for this type of combinatorial problem.

Here's the breakdown of the solution:

  • The Solution class contains a method countTrees which takes a single argument m representing the number of nodes.
  • A variable total is initialized to 1. This variable will store the result which computes the total number of unique trees.
  • The method employs a for loop that iterates from 0 up to m. During each iteration, the variable total is updated using the formula for Catalan numbers. Specifically, total is multiplied by 2 * (2 * j + 1) and then divided by (j + 2).
  • Importantly, the formula simultaneously multiplies and divides total in each iteration to build the Catalan number incrementally.
  • After completing the iterations, the function converts total to an integer using int(total) and returns this value. This conversion ensures that the function outputs a whole number, as the number of unique binary search trees must be an integer.

The efficient use of the Catalan number in this calculation allows for determining the number of unique binary search trees without constructing each tree, thus significantly improving the computational complexity compared to a naive approach.

Comments

No comments yet.