Given n, how many distinct Max Heap can be made from n distinct integers?

Examples:

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

Since there is only one element as the **root**, it must be the largest number. Now we have n-1 remaining elements. The main observation here is that because of the max heap properties, the **structure** of the heap nodes will remain the same in all instances, but only the values in the nodes will change.

Assume there are **l** elements in the **left sub-tree** and **r** elements in the **right sub-tree**. Now for the root, l + r = n-1. From this we can see that we can **choose** any l of the remaining n-1 elements for the left sub-tree as they are all smaller than the root.

We know the there are ways to do this. Next for each instance of these, we can have many heaps with l elements and for each of those we can have many heaps with r elements. Thus we can consider them as subproblems and **recur** for the final answer as:

T(n) = * T(L) * T(R).

Now we have to find the **values** for l and r for a given n. We know that the height of the heap h = . Also the maximum number of elements that can be present in the h th **level** of any heap, m = , where the root is at the 0th level. Moreover the number of elements actually present in the last level of the heap p = n – ( – 1). (since number of nodes present till the penultimate level). Thus, there can be two **cases**: when the last level is more than or equal to half-filled:

l = – 1, if p >= m / 2

(or) the last level is less than half-filled:

l = – 1 – ((m / 2) – p), if p < m / 2

(we get – 1 here because left subtree has nodes.

From this we can also say that r = n – l – 1.

We can use the **dynamic programming** approach discussed in this post here to find the values of . Similarly if we look at the recursion tree for the **optimal substructure** recurrence formed above, we can see that it also has **overlapping subproblems** property, hence can be solved using dynamic programming:

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

Following is the c++ implementation of the above approach:

`// CPP program to count max heaps with n distinct keys ` `#include <iostream> ` `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; ` `} ` |

Output:

3360

Asked in: Directi.

## Recommended Posts:

- Number of ordered pairs such that (Ai & Aj) = 0
- K maximum sum combinations from two arrays
- Johnson and Trotter algorithm
- Maximum distinct elements after removing k elements
- Largest rectangular sub-matrix whose sum is 0
- Median of Stream of Running Integers using STL
- Modify array to maximize sum of adjacent differences
- Ways to write n as sum of two or more positive integers
- Merge K sorted linked lists | Set 1
- Compute sum of digits in all numbers from 1 to n
- Binary Heap
- Merge k sorted arrays | Set 1
- HeapSort
- Binomial Coefficient | DP-9
- Median in a stream of integers (running integers)

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.