Build Array Where You Can Find The Maximum Exactly K Comparisons

HARD

Description

You are given three integers n, m and k. Consider the following algorithm to find the maximum element of an array of positive integers:

You should build the array arr which has the following properties:

  • arr has exactly n integers.
  • 1 <= arr[i] <= m where (0 <= i < n).
  • After applying the mentioned algorithm to arr, the value search_cost is equal to k.

Return the number of ways to build the array arr under the mentioned conditions. As the answer may grow large, the answer must be computed modulo 109 + 7.

 

Example 1:

Input: n = 2, m = 3, k = 1
Output: 6
Explanation: The possible arrays are [1, 1], [2, 1], [2, 2], [3, 1], [3, 2] [3, 3]

Example 2:

Input: n = 5, m = 2, k = 3
Output: 0
Explanation: There are no possible arrays that satisfy the mentioned conditions.

Example 3:

Input: n = 9, m = 1, k = 1
Output: 1
Explanation: The only possible array is [1, 1, 1, 1, 1, 1, 1, 1, 1]

 

Constraints:

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

Approaches

Checkout 3 different approaches to solve Build Array Where You Can Find The Maximum Exactly K Comparisons. Click on different approaches to view the approach and algorithm in detail.

Bottom-Up DP with Prefix Sum Optimization

This approach uses bottom-up dynamic programming. We define a 3D DP state dp[i][j][l] representing the number of ways to build an array of length i with a maximum value of exactly j and a search cost of l. The key to improving efficiency over the naive DP is to optimize the transition. The transition requires summing up values from the previous state, which can be done efficiently using a prefix sum technique, reducing the complexity of each state calculation from O(m) to O(1).

Algorithm

  • Initialize a 3D DP table dp[n+1][m+1][k+1].
  • Set base cases: dp[1][j][1] = 1 for j from 1 to m.
  • Iterate i from 2 to n (length of array).
  • Iterate l from 1 to k (cost).
  • Initialize prefixSum = 0.
  • Iterate j from 1 to m (max value).
    • Calculate dp[i][j][l] = (dp[i-1][j][l] * j + prefixSum) % MOD.
    • Update prefixSum = (prefixSum + dp[i-1][j][l-1]) % MOD.
  • Sum up dp[n][j][k] for all j from 1 to m to get the final answer.

Let dp[i][j][l] be the number of ways to construct an array of length i such that its maximum element is j and the search cost is l. Our goal is to compute sum(dp[n][j][k]) for all j from 1 to m.

Base Case: For an array of length 1, arr = [j], the maximum is j and the cost is 1. So, dp[1][j][1] = 1 for 1 <= j <= m.

Recurrence Relation: To compute dp[i][j][l], we consider how the i-th element is added to an array of length i-1.

  • Case 1: The i-th element is not a new maximum. This means the maximum of the first i-1 elements was already j, and the i-th element is chosen from 1, ..., j. There are j choices for the i-th element. The number of ways is dp[i-1][j][l] * j.
  • Case 2: The i-th element is a new maximum, and its value is j. This means the maximum of the first i-1 elements was some value p < j, and the cost for the prefix was l-1. The number of ways is the sum of dp[i-1][p][l-1] for all p from 1 to j-1.

The full recurrence is: dp[i][j][l] = (dp[i-1][j][l] * j) + (sum_{p=1}^{j-1} dp[i-1][p][l-1]).

Optimization: The summation term sum_{p=1}^{j-1} dp[i-1][p][l-1] is a prefix sum. As we iterate j from 1 to m (for fixed i and l), we can maintain this sum in a variable, updating it in O(1) at each step.

class Solution {
    public int numOfArrays(int n, int m, int k) {
        if (k == 0) return 0;
        int MOD = 1_000_000_007;
        long[][][] dp = new long[n + 1][m + 1][k + 1];

        // Base case: for length 1, any max j in [1, m] has cost 1.
        for (int j = 1; j <= m; j++) {
            dp[1][j][1] = 1;
        }

        for (int i = 2; i <= n; i++) {
            for (int l = 1; l <= k; l++) {
                long prefixSum = 0;
                for (int j = 1; j <= m; j++) {
                    // Case 1: The i-th element is not a new maximum.
                    long ways = (dp[i - 1][j][l] * j) % MOD;
                    
                    // Case 2: The i-th element is a new maximum, j.
                    // The prefix sum is sum_{p=1}^{j-1} dp[i-1][p][l-1].
                    ways = (ways + prefixSum) % MOD;
                    
                    dp[i][j][l] = ways;

                    // Update prefix sum for the next iteration of j.
                    prefixSum = (prefixSum + dp[i - 1][j][l - 1]) % MOD;
                }
            }
        }

        long ans = 0;
        for (int j = 1; j <= m; j++) {
            ans = (ans + dp[n][j][k]) % MOD;
        }
        return (int)ans;
    }
}

Complexity Analysis

Time Complexity: O(n * m * k). We have three nested loops for `i`, `l`, and `j`. The operations inside the innermost loop are `O(1)`.Space Complexity: O(n * m * k). For the 3D DP table.

Pros and Cons

Pros:
  • Much more efficient than the unoptimized DP due to the prefix sum calculation.
  • A systematic, iterative approach that avoids recursion overhead.
Cons:
  • Requires a large amount of memory for the 3D DP table.

Code Solutions

Checking out 3 solutions in different languages for Build Array Where You Can Find The Maximum Exactly K Comparisons. Click on different languages to view the code.

class Solution {
private
  static final int MOD = (int)1 e9 + 7;
public
  int numOfArrays(int n, int m, int k) {
    if (k == 0) {
      return 0;
    }
    long[][][] dp = new long[n + 1][k + 1][m + 1];
    for (int i = 1; i <= m; ++i) {
      dp[1][1][i] = 1;
    }
    for (int i = 2; i <= n; ++i) {
      for (int c = 1; c <= Math.min(i, k); ++c) {
        for (int j = 1; j <= m; ++j) {
          dp[i][c][j] = (dp[i - 1][c][j] * j) % MOD;
          for (int j0 = 1; j0 < j; ++j0) {
            dp[i][c][j] = (dp[i][c][j] + dp[i - 1][c - 1][j0]) % MOD;
          }
        }
      }
    }
    long ans = 0;
    for (int i = 1; i <= m; ++i) {
      ans = (ans + dp[n][k][i]) % MOD;
    }
    return (int)ans;
  }
}

Video Solution

Watch the video walkthrough for Build Array Where You Can Find The Maximum Exactly K Comparisons



Patterns:

Dynamic ProgrammingPrefix Sum

Companies:

Subscribe to Scale Engineer newsletter

Learn about System Design, Software Engineering, and interview experiences every week.

No spam, unsubscribe at any time.