📌  相关文章
📜  形成具有 n 个不同整数的堆的方法数

📅  最后修改于: 2021-10-28 02:02:14             🧑  作者: Mango

给定 n,n 个不同的整数可以组成多少个不同的最大堆?
例子:

Input : n = 3
Output : Assume the integers are 1, 2, 3.
Then the 2 possible max heaps are:       
            3
           / \
          1   2

           3
          / \
         2   1

Input : n = 4
Output : Assume the integers are 1, 2, 3, 4.
Then the 3 possible max heaps are:
        4 
       / \ 
      3   2 
     / 
    1

        4 
       / \ 
      2   3 
     / 
    1

        4 
       / \ 
      3   1 
     / 
    2

由于只有一个元素作为root ,所以它必须是最大的数字。现在我们有 n-1 个剩余元素。这里的主要观察是由于最大堆属性,堆节点的结构将在所有实例中保持不变,但只有节点中的值会发生变化。
假设有在右子树左子树R元素L型元件。现在对于根,l + r = n-1。由此我们可以看出,我们可以为左子树选择剩余的 n-1 个元素中的任意 l 个,因为它们都小于根。
我们知道有\binom{n-1}{l}  方法来做到这一点。接下来,对于这些实例的每个实例,我们可以有许多包含 l 个元素的堆,而对于其中的每一个,我们可以拥有许多包含 r 个元素的堆。因此,我们可以将它们视为子问题,并重复得到最终答案:
T(n) = \binom{n-1}{l}  * T(L) * T(R)。
现在我们必须找到给定 n 的 l 和 r 的。我们知道堆的高度 h = \log_2 n  .也是任何堆的第 h中可以存在的最大元素数,m = 2^h  ,其中根在第 0 层。此外,堆的最后一层中实际存在的元素数量 p = n – ( 2^h  – 1)。 (自从2^h - 1  存在到倒数第二个级别的节点数)。因此,可能有两种情况:当最后一层大于或等于半满时:
升 = 2^h  – 1,如果 p >= m / 2
(或) 最后一关未满:
升 = 2^h  – 1 – ((m / 2) – p),如果 p < m / 2
(我们得到2^h  – 1 这里是因为左子树有2^0 + 2^1 +..+2^{h-1}  节点。
由此我们也可以说 r = n – l – 1。
我们可以使用本文中讨论的动态规划方法来找到\binom{n}{k}  .类似地,如果我们查看上面形成的最优子结构递归的递归树,我们可以看到它也具有重叠子问题的性质,因此可以使用动态规划解决:

T(7)
            /    \
          T(3)   T(3)
         /  \     /  \    
     T(1)  T(1) T(1) T(1) 

以下是上述方法的实现:

C++
// CPP program to count max heaps with n distinct keys
#include 
using namespace std;
 
#define MAXN 105 // maximum value of n here
 
// dp[i] = number of max heaps for i distinct integers
int dp[MAXN];
 
// nck[i][j] = number of ways to choose j elements
//             form i elements, no order */
int nck[MAXN][MAXN];
 
// log2[i] = floor of logarithm of base 2 of i
int log2[MAXN];
 
// to calculate nCk
int choose(int n, int k)
{
    if (k > n)
        return 0;
    if (n <= 1)
        return 1;
    if (k == 0)
        return 1;
 
    if (nck[n][k] != -1)
        return nck[n][k];
 
    int answer = choose(n - 1, k - 1) + choose(n - 1, k);
    nck[n][k] = answer;
    return answer;
}
 
// calculate l for give value of n
int getLeft(int n)
{
    if (n == 1)
        return 0;
 
    int h = log2[n];
 
    // max number of elements that can be present in the
    // hth level of any heap
    int numh = (1 << h); //(2 ^ h)
 
    // number of elements that are actually present in
    // last level(hth level)
    // (2^h - 1)
    int last = n - ((1 << h) - 1);
 
    // if more than half-filled
    if (last >= (numh / 2))
        return (1 << h) - 1; // (2^h) - 1
    else
        return (1 << h) - 1 - ((numh / 2) - last);
}
 
// find maximum number of heaps for n
int numberOfHeaps(int n)
{
    if (n <= 1)
        return 1;
 
    if (dp[n] != -1)
        return dp[n];
 
    int left = getLeft(n);
    int ans = (choose(n - 1, left) * numberOfHeaps(left)) *
                             (numberOfHeaps(n - 1 - left));
    dp[n] = ans;
    return ans;
}
 
// function to initialize arrays
int solve(int n)
{
    for (int i = 0; i <= n; i++)
        dp[i] = -1;
 
    for (int i = 0; i <= n; i++)
        for (int j = 0; j <= n; j++)
            nck[i][j] = -1;
 
    int currLog2 = -1;
    int currPower2 = 1;
 
    // for each power of two find logarithm
    for (int i = 1; i <= n; i++) {
        if (currPower2 == i) {
            currLog2++;
            currPower2 *= 2;
        }
        log2[i] = currLog2;
    }
 
    return numberOfHeaps(n);
}
 
// driver function
int main()
{
    int n = 10;
    cout << solve(n) << endl;
    return 0;
}


Java
// Java program to count max heaps with n distinct keys
class GFG
{
 
    static int MAXN = 105; // maximum value of n here
 
    // dp[i] = number of max heaps for i distinct integers
    static int[] dp = new int[MAXN];
 
    // nck[i][j] = number of ways to choose j elements
    //         form i elements, no order */
    static int[][] nck = new int[MAXN][MAXN];
 
    // log2[i] = floor of logarithm of base 2 of i
    static int[] log2 = new int[MAXN];
 
    // to calculate nCk
    public static int choose(int n, int k)
    {
        if (k > n)
        {
            return 0;
        }
        if (n <= 1)
        {
            return 1;
        }
        if (k == 0)
        {
            return 1;
        }
 
        if (nck[n][k] != -1)
        {
            return nck[n][k];
        }
 
        int answer = choose(n - 1, k - 1) + choose(n - 1, k);
        nck[n][k] = answer;
        return answer;
    }
 
    // calculate l for give value of n
    public static int getLeft(int n)
    {
        if (n == 1)
        {
            return 0;
        }
 
        int h = log2[n];
 
        // max number of elements that can be present in the
        // hth level of any heap
        int numh = (1 << h); //(2 ^ h)
 
        // number of elements that are actually present in
        // last level(hth level)
        // (2^h - 1)
        int last = n - ((1 << h) - 1);
 
        // if more than half-filled
        if (last >= (numh / 2))
        {
            return (1 << h) - 1; // (2^h) - 1
        }
        else
        {
            return (1 << h) - 1 - ((numh / 2) - last);
        }
    }
 
    // find maximum number of heaps for n
    public static int numberOfHeaps(int n)
    {
        if (n <= 1)
        {
            return 1;
        }
 
        if (dp[n] != -1)
        {
            return dp[n];
        }
 
        int left = getLeft(n);
        int ans = (choose(n - 1, left) * numberOfHeaps(left))
                * (numberOfHeaps(n - 1 - left));
        dp[n] = ans;
        return ans;
    }
 
    // function to initialize arrays
    public static int solve(int n)
    {
        for (int i = 0; i <= n; i++)
        {
            dp[i] = -1;
        }
 
        for (int i = 0; i <= n; i++)
        {
            for (int j = 0; j <= n; j++)
            {
                nck[i][j] = -1;
            }
        }
 
        int currLog2 = -1;
        int currPower2 = 1;
 
        // for each power of two find logarithm
        for (int i = 1; i <= n; i++)
        {
            if (currPower2 == i)
            {
                currLog2++;
                currPower2 *= 2;
            }
            log2[i] = currLog2;
        }
 
        return numberOfHeaps(n);
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int n = 10;
        System.out.print(solve(n));
    }
}
 
// This code has been contributed by 29AjayKumar


Python3
# Python program to count max heaps with n distinct keys
 
MAXN = 105 # maximum value of n here
 
# dp[i] = number of max heaps for i distinct integers
dp = [0]*MAXN
 
# nck[i][j] = number of ways to choose j elements
#             form i elements, no order */
nck = [[0 for i in range(MAXN)] for j in range(MAXN)]
 
# log2[i] = floor of logarithm of base 2 of i
log2 = [0]*MAXN
 
# to calculate nCk
def choose(n, k):
    if (k > n):
        return 0
    if (n <= 1):
        return 1
    if (k == 0):
        return 1
 
    if (nck[n][k] != -1):
        return nck[n][k]
 
    answer = choose(n - 1, k - 1) + choose(n - 1, k)
    nck[n][k] = answer
    return answer
 
 
# calculate l for give value of n
def getLeft(n):
    if (n == 1):
        return 0
 
    h = log2[n]
 
    # max number of elements that can be present in the
    # hth level of any heap
    numh = (1 << h) #(2 ^ h)
 
    # number of elements that are actually present in
    # last level(hth level)
    # (2^h - 1)
    last = n - ((1 << h) - 1)
 
    # if more than half-filled
    if (last >= (numh // 2)):
        return (1 << h) - 1 # (2^h) - 1
    else:
        return (1 << h) - 1 - ((numh // 2) - last)
 
 
# find maximum number of heaps for n
def numberOfHeaps(n):
    if (n <= 1):
        return 1
 
    if (dp[n] != -1):
        return dp[n]
 
    left = getLeft(n)
    ans = (choose(n - 1, left) * numberOfHeaps(left)) * (numberOfHeaps(n - 1 - left))
    dp[n] = ans
    return ans
 
 
# function to initialize arrays
def solve(n):
    for i in range(n+1):
        dp[i] = -1
 
    for i in range(n+1):
        for j in range(n+1):
            nck[i][j] = -1
 
    currLog2 = -1
    currPower2 = 1
 
    # for each power of two find logarithm
    for i in range(1,n+1):
        if (currPower2 == i):
            currLog2 += 1
            currPower2 *= 2
        log2[i] = currLog2
    return numberOfHeaps(n)
 
 
# Driver code
n = 10
print(solve(n))
 
# This code is contributed by ankush_953


C#
// C# program to count max heaps with n distinct keys
using System;
   
class GFG
{
    static int MAXN = 105; // maximum value of n here
       
    // dp[i] = number of max heaps for i distinct integers
    static int[] dp = new int[MAXN]; 
       
    // nck[i][j] = number of ways to choose j elements
    //             form i elements, no order */
    static int[,] nck = new int[MAXN,MAXN]; 
       
    // log2[i] = floor of logarithm of base 2 of i
    static int[] log2 = new int[MAXN]; 
       
    // to calculate nCk
    public static int choose(int n, int k)
    {
        if (k > n)
            return 0;
        if (n <= 1)
            return 1;
        if (k == 0)
            return 1;
       
        if (nck[n,k] != -1)
            return nck[n,k];
       
        int answer = choose(n - 1, k - 1) + choose(n - 1, k);
        nck[n,k] = answer;
        return answer;
    }
       
    // calculate l for give value of n
    public static int getLeft(int n)
    {
        if (n == 1)
            return 0;
       
        int h = log2[n];
       
        // max number of elements that can be present in the 
        // hth level of any heap
        int numh = (1 << h); //(2 ^ h)
       
        // number of elements that are actually present in
        // last level(hth level)
        // (2^h - 1)
        int last = n - ((1 << h) - 1);
       
        // if more than half-filled
        if (last >= (numh / 2))
            return (1 << h) - 1; // (2^h) - 1
        else
            return (1 << h) - 1 - ((numh / 2) - last);
    }
       
    // find maximum number of heaps for n
    public static int numberOfHeaps(int n)
    {
        if (n <= 1)
            return 1;
       
        if (dp[n] != -1)
            return dp[n];
       
        int left = getLeft(n);
        int ans = (choose(n - 1, left) * numberOfHeaps(left)) * 
                                 (numberOfHeaps(n - 1 - left));
        dp[n] = ans;
        return ans;
    }
       
    // function to initialize arrays
    public static int solve(int n)
    {
        for (int i = 0; i <= n; i++)
            dp[i] = -1;
       
        for (int i = 0; i <= n; i++)
            for (int j = 0; j <= n; j++)
                nck[i,j] = -1;
       
        int currLog2 = -1;
        int currPower2 = 1;
       
        // for each power of two find logarithm
        for (int i = 1; i <= n; i++) {
            if (currPower2 == i) {
                currLog2++;
                currPower2 *= 2;
            }
            log2[i] = currLog2;
        }
       
        return numberOfHeaps(n);
    }
       
    // driver function
    static void Main()
    {
        int n = 10;
        Console.Write(solve(n));
    }
    //This code is contributed by DrRoot_
}


Javascript


输出:

3360

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程