[LeetCode 1420]最大Kの比較を見つけることができる配列を構築する

与えられた3つの整数  n、  m および  k正の整数の配列の最大要素を見つけるには、次のアルゴリズムを検討してください。

次のプロパティを持つ配列arrを構築する必要があります。

  • arr 正確にn 整数を持ってい  ます。
  • 1 <= arr[i] <= m どこ  (0 <= i < n)
  • 上記のアルゴリズムをに適用する  arrと、値  search_cost はに等しくなり  kます。

 上記の条件下で 配列を構築する  方法の数を返し  arrます。答えが大きくなる可能性があるため、答えはmoduloで計算する必要があります  10^9 + 7

 

例1:

入力:n = 2、m = 3、k = 1
出力:6
説明:可能な配列は[1、1]、[2、1]、[2、2]、[3、1]、[3、2] [3、3]です

例2:

入力:n = 5、m = 2、k = 3
出力:0
説明:上記の条件を満足する可能性のあるアレイはありません。

例3:

入力:n = 9、m = 1、k = 1
出力:1
説明:可能な配列は[1、1、1、1、1、1、1、1、1]のみです

例4:

入力:n = 50、m = 100、k = 25
出力:34549172
説明:1000000007を法とする答えを計算することを忘れないでください

例5:

入力:n = 37、m = 17、k = 7
出力:418930126

 

制約:

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

 

O(N * K * M ^ 2)動的プログラミング

 

状態:

dp [i] [j] [maxV]:arr [0、i](長さi + 1)の配列を作成する方法の数。jの検索コストとmaxVの最大数。 

遷移:

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;
    }
}

 

おすすめ

転載: www.cnblogs.com/lz87/p/12742029.html