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.

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 write comments if you find anything incorrect, or you want to share more information about the topic discussed above.