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

📅  最后修改于: 2021-06-25 14:57:37             🧑  作者: Mango

给定n,可以从n个不同的整数中制作多少个不同的Max Heap?

例子:

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

由于只有一个元素作为,因此它必须是最大数目。现在我们还有n-1个剩余元素。此处的主要观察结果是,由于具有最大堆属性,所以堆节点的结构在所有实例中都将保持不变,但是只有节点中的值会更改。

假设有在右子树左子树R元素L型元件。现在对于根,l + r = n-1。由此可见,我们可以为左子树选择其余n-1个元素中的任意一个,因为它们都比根小。
我们知道有 \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直到倒数第二级为止的节点数)。因此,可能有两种情况:当最后一个级别大于或等于一半填充时:
l = 2^h – 1,如果p> = m / 2
(或)最后一级未满一半:
l = 2^h – 1 –(((m / 2)– p),如果p (我们得到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_
}


输出:

3360