Dado n, ¿cuántos Max Heap distintos se pueden hacer a partir de n enteros distintos?
Ejemplos:
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
Como solo hay un elemento como raíz , debe ser el número más grande. Ahora tenemos n-1 elementos restantes. La observación principal aquí es que debido a las propiedades máximas del montón, la estructura de los Nodes del montón seguirá siendo la misma en todas las instancias, pero solo cambiarán los valores en los Nodes.
Suponga que hay l elementos en el subárbol izquierdo y r elementos en el subárbol derecho . Ahora para la raíz, l + r = n-1. A partir de esto, podemos ver que podemos elegir cualquier l de los n-1 elementos restantes para el subárbol izquierdo, ya que todos son más pequeños que la raíz.
Sabemos que hay maneras de hacer esto. A continuación, para cada instancia de estos, podemos tener muchos montones con l elementos y para cada uno de ellos podemos tener muchos montones con r elementos. Así podemos considerarlos como subproblemas y recurrir a la respuesta final como:
T(n) = * T(L) * T(R).
Ahora tenemos que encontrar los valores de l y r para un n dado. Sabemos que la altura del montón h = . También el número máximo de elementos que pueden estar presentes en el nivel h de cualquier montón, m = , donde la raíz está en el nivel 0. Además, el número de elementos realmente presentes en el último nivel del montón p = n – ( – 1). (desde número de Nodes presentes hasta el penúltimo nivel). Así, puede haber dos casos : cuando el último nivel está más o igual a la mitad:
l = – 1, si p >= m / 2
(o) el último nivel está a menos de la mitad:
l = – 1 – ((m / 2) – p), si p < m / 2
(obtenemos – 1 aquí porque el subárbol izquierdo tiene Nodes.
A partir de esto podemos decir también que r = n – l – 1.
Podemos usar el enfoque de programación dinámica discutido en esta publicación aquí para encontrar los valores de . De manera similar, si observamos el árbol de recurrencia para la recurrencia óptima de la subestructura formada anteriormente, podemos ver que también tiene la propiedad de subproblemas superpuestos , por lo tanto, se puede resolver mediante programación dinámica:
T(7) / \ T(3) T(3) / \ / \ T(1) T(1) T(1) T(1)
La siguiente es la implementación del enfoque anterior:
C++
// 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; }
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
<script> // JavaScript program to count max heaps with n distinct keys let MAXN = 105; // maximum value of n here // dp[i] = number of max heaps for i distinct integers let dp = new Array(MAXN); // nck[i][j] = number of ways to choose j elements // form i elements, no order */ let nck = new Array(MAXN); for(let i=0;i<MAXN;i++) { nck[i]=new Array(MAXN); for(let j=0;j<MAXN;j++) nck[i][j]=0; } // log2[i] = floor of logarithm of base 2 of i let log2 = new Array(MAXN); // to calculate nCk function 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]; } let answer = choose(n - 1, k - 1) + choose(n - 1, k); nck[n][k] = answer; return answer; } // calculate l for give value of n function getLeft(n) { if (n == 1) { return 0; } let h = log2[n]; // max number of elements that can be present in the // hth level of any heap let numh = (1 << h); //(2 ^ h) // number of elements that are actually present in // last level(hth level) // (2^h - 1) let 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 function numberOfHeaps(n) { if (n <= 1) { return 1; } if (dp[n] != -1) { return dp[n]; } let left = getLeft(n); let ans = (choose(n - 1, left) * numberOfHeaps(left)) * (numberOfHeaps(n - 1 - left)); dp[n] = ans; return ans; } // function to initialize arrays function solve(n) { for (let i = 0; i <= n; i++) { dp[i] = -1; } for (let i = 0; i <= n; i++) { for (let j = 0; j <= n; j++) { nck[i][j] = -1; } } let currLog2 = -1; let currPower2 = 1; // for each power of two find logarithm for (let i = 1; i <= n; i++) { if (currPower2 == i) { currLog2++; currPower2 *= 2; } log2[i] = currLog2; } return numberOfHeaps(n); } // Driver code let n = 10; document.write(solve(n)); // This code is contributed by rag2127 </script>
3360
Publicación traducida automáticamente
Artículo escrito por rsatish1110 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA