📜  使用加泰罗尼亚语编号的可能二进制搜索树的总数

📅  最后修改于: 2021-04-23 21:28:11             🧑  作者: Mango

给定整数N ,任务是计算具有N个关键字的可能的二叉搜索树的数量。

例子:

Input: N = 2
Output: 2
For N = 2, there are 2 unique BSTs
     1               2  
      \            /
       2         1

Input: N = 9
Output: 4862

方法:可以通过简单地评估加泰罗尼亚语数字系列中的相应数字来计算将使用N个关键字形成的二叉搜索树的数量。
n = 0、1、2、3,…的前几个加泰罗尼亚数字是1、1、2、5、14、42、132、429、1430、4862 …
加泰罗尼亚语数字满足以下递归公式:

C_0=1 \ and \ C_n_+_1=\sum_{i=0}^{n}C_iC_n_-_i \ for \ n\geq 0;

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
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
// 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
# 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#
// 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.


C++
// C++ dynamic programming implementation of the approach
#include 
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
// 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
# 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


输出
2

该问题可以通过动态编程的方式解决。
以下是递归树将如何进行的摘要:

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                        

注意:如果没有备忘录,则时间复杂度的上限为O(N x N!)。
给定一个序列1…n,要从该序列中构造一个二叉搜索树(BST),我们可以枚举序列中的每个数字i,并使用该数字作为根,自然地,子序列1…(i-1)它的左侧将位于根的左分支上,类似地,右子序列(i + 1)…n则位于根的右分支上。然后,我们可以从子序列递归构造子树。通过上述方法,我们可以确保我们构建的BST都是唯一的,因为它们具有唯一的根。

问题是要计算唯一BST的数量。为此,我们需要定义两个函数:

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) 

在计算方面,我们需要从较低的数字开始,因为G(n)的值
取决于G(0)…G(n-1)的值。

下面是上述算法的以上实现:

C++

// C++ dynamic programming implementation of the approach
#include 
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

// 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

# 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
输出
2

时间复杂度: O(N 2 )  
空间复杂度:O(N)