[LeetCode 1420] Build Array donde puede encontrar el máximo Exactamente K Comparaciones

Dados tres enteros  nm y  k. Considere el siguiente algoritmo para encontrar el elemento máximo de una matriz de enteros positivos:

Debe compilar la matriz arr que tiene las siguientes propiedades:

  • arr tiene exactamente  n enteros.
  • 1 <= arr[i] <= m donde  (0 <= i < n).
  • Después de aplicar el algoritmo mencionado a  arr, el valor  search_cost es igual a  k.

Devuelve  el número de formas  de construir la matriz  arr en las condiciones mencionadas. Como la respuesta puede crecer, la respuesta debe calcularse en módulo  10^9 + 7.

 

Ejemplo 1:

Entrada: n = 2, m = 3, k = 1 
Salida: 6 
Explicación: Las posibles matrices son [1, 1], [2, 1], [2, 2], [3, 1], [3, 2 ] [3, 3]

Ejemplo 2

Entrada: n = 5, m = 2, k = 3 
Salida: 0 
Explicación: No hay posibles matrices que satisfagan las condiciones mencionadas.

Ejemplo 3

Entrada: n = 9, m = 1, k = 1 
Salida: 1 
Explicación: La única matriz posible es [1, 1, 1, 1, 1, 1, 1, 1, 1]

Ejemplo 4

Entrada: n = 50, m = 100, k = 25 
Salida: 34549172 
Explicación: No olvide calcular el módulo de respuesta 1000000007

Ejemplo 5:

Entrada: n = 37, m = 17, k = 7 
Salida: 418930126

 

Restricciones:

  • 1 <= n <= 50
  • 1 <= m <= 100
  • 0 <= k <= n

 

O (N * K * M ^ 2) programación dinámica

 

Estado:

dp[i][j][maxV]: the number of ways to build an array of arr[0, i] (length i + 1), with j search costs and max number of maxV. 

Transition:

1. if the current value V is not a new max number, then V must be in range [1, maxV], otherwise V will be a new max number. So the current number has maxV different choices, each choice corresponds to the number of ways of shorter length by 1, same search cost and max number, dp[i - 1][j][maxV]. So dp[i][j][maxV] += dp[i - 1][j][maxV] * maxV;  

 

2. if the current value V is a new max number, then V only has one option, maxV. We can append maxV to all arrays of shorter length by 1, smaller search cost by 1 and max value smaller than maxV to get array of longer length by 1, bigger search cost by 1 and max number maxV. So dp[i][j][maxV] = Sum of (dp[i - 1][j - 1][smallerV]), smallerV in [1, maxV - 1].

 

Init:

For array of 1 element, there is 1 way for each different number choice with a search cost of 1. This is true because maximum value is initially set to < 0, so any number choice will incur an update.  dp[0][1][maxV] = 1, maxV in [1, m].

 

Answer: Sum of dp[n - 1][k][maxV], maxV in [1, m]. For each valid array, its max value must be in [1, m], so the final answer is the sum over all max value possibilities for length n and search cost k.

 

class Solution {
    public int numOfArrays(int n, int m, int k) {
        int mod = (int)1e9 + 7;
        long[][][] dp = new long[n][k + 1][m + 1];
        for(int maxV = 1; maxV <= m; maxV++) {
            dp[0][1][maxV] = 1;
        }
        for(int i = 1; i < n; i++) {
            for(int j = 1; j <= k; j++) {
                for(int maxV = 1; maxV <= m; maxV++) {
                    //newly added number is not a new max value
                    dp[i][j][maxV] = (dp[i][j][maxV] + dp[i - 1][j][maxV] * maxV) % mod;
                    //newly added number is a new max value
                    for(int smallerV = 1; smallerV < maxV; smallerV++) {
                        dp[i][j][maxV] = (dp[i][j][maxV] + dp[i - 1][j - 1][smallerV]) % mod;
                    }
                }
            }
        }
        long ans = 0;
        for(int v = 1; v <= m; v++) {
            ans = (ans + dp[n - 1][k][v]) % mod;
        }
        return (int)ans;
    }
}

 

 

The for loop to for case: newly added number is a new max value does redundant work as it sums up the same prefixes dp[i - 1][j - 1][smallerV] repeatly. To optimize this, we can create a prefix sum array to save the previous summation results. This reduces the runtime of computing newly added number is a new max value case from O(M) to O(1). 

 

class Solution {
    public int numOfArrays(int n, int m, int k) {
        int mod = (int)1e9 + 7;
        long[][][] dp = new long[n][k + 1][m + 1];
        long[][][] ps = new long[n][k + 1][m + 1];
        for(int maxV = 1; maxV <= m; maxV++) {
            dp[0][1][maxV] = 1;
            ps[0][1][maxV] = ps[0][1][maxV - 1] + 1;
        }
        for(int i = 1; i < n; i++) {
            for(int j = 1; j <= k; j++) {
                for(int maxV = 1; maxV <= m; maxV++) {
                    //newly added number is not a new max value
                    dp[i][j][maxV] = (dp[i][j][maxV] + dp[i - 1][j][maxV] * maxV) % mod;
                    //newly added number is a new max value
                    dp[i][j][maxV] = (dp[i][j][maxV] + ps[i - 1][j - 1][maxV - 1]) % mod;
                    ps[i][j][maxV] = (ps[i][j][maxV - 1] + dp[i][j][maxV]) % mod;
                }
            }
        }
        long ans = 0;
        for(int v = 1; v <= m; v++) {
            ans = (ans + dp[n - 1][k][v]) % mod;
        }
        return (int)ans;
    }
}

 

Supongo que te gusta

Origin www.cnblogs.com/lz87/p/12742029.html
Recomendado
Clasificación