Minimum Operations to Make Elements Within K Subarrays Equal

Hard
#3117Time: O(n * x * log(x) + n * k) - The cost calculation step dominates. There are `O(n)` windows, and for each, we sort `x` elements, taking `O(x log x)`. The DP part takes `O(n*k)`.Space: O(n*k) - We need `O(n)` space for the `costs` array and `O(n*k)` for the DP table.

Prompt

You are given an integer array nums and two integers, x and k. You can perform the following operation any number of times (including zero):

  • Increase or decrease any element of nums by 1.

Return the minimum number of operations needed to have at least k non-overlapping subarrays of size exactly x in nums, where all elements within each subarray are equal.

 

Example 1:

Input: nums = [5,-2,1,3,7,3,6,4,-1], x = 3, k = 2

Output: 8

Explanation:

  • Use 3 operations to add 3 to nums[1] and use 2 operations to subtract 2 from nums[3]. The resulting array is [5, 1, 1, 1, 7, 3, 6, 4, -1].
  • Use 1 operation to add 1 to nums[5] and use 2 operations to subtract 2 from nums[6]. The resulting array is [5, 1, 1, 1, 7, 4, 4, 4, -1].
  • Now, all elements within each subarray [1, 1, 1] (from indices 1 to 3) and [4, 4, 4] (from indices 5 to 7) are equal. Since 8 total operations were used, 8 is the output.

Example 2:

Input: nums = [9,-2,-2,-2,1,5], x = 2, k = 2

Output: 3

Explanation:

  • Use 3 operations to subtract 3 from nums[4]. The resulting array is [9, -2, -2, -2, -2, 5].
  • Now, all elements within each subarray [-2, -2] (from indices 1 to 2) and [-2, -2] (from indices 3 to 4) are equal. Since 3 operations were used, 3 is the output.

 

Constraints:

  • 2 <= nums.length <= 105
  • -106 <= nums[i] <= 106
  • 2 <= x <= nums.length
  • 1 <= k <= 15
  • 2 <= k * x <= nums.length

Approaches

3 approaches with complexity analysis and trade-offs.

This approach involves two main stages. First, it pre-calculates the minimum operations (cost) required to make each possible subarray of size x have all equal elements. This is done naively by sorting each subarray to find its median and then summing the absolute differences. Second, it uses dynamic programming to determine the minimum total cost to select k non-overlapping subarrays from the calculated costs.

Algorithm

  • Step 1: Pre-calculate Subarray Costs (Naively)
    1. Create a costs array of size n - x + 1.
    2. Iterate from i = 0 to n - x.
    3. For each i, extract the subarray nums[i...i+x-1].
    4. Sort the subarray to find its median (element at index (x-1)/2).
    5. Calculate the sum of absolute differences of each element from the median. This is costs[i].
  • Step 2: Dynamic Programming
    1. Create a 2D DP table dp of size (n - x + 2) x (k + 1), initialized to a large value.
    2. Set the base case: dp[i][0] = 0 for all i (cost of 0 subarrays is 0).
    3. Iterate j from 1 to k (number of subarrays).
    4. Iterate i from 1 to n - x + 1 (number of possible starting positions).
    5. Calculate dp[i][j] using the recurrence: dp[i][j] = min(dp[i-1][j], costs[i-1] + dp[i-x][j-1]).
      • dp[i-1][j] represents not selecting the subarray starting at i-1.
      • costs[i-1] + dp[i-x][j-1] represents selecting the subarray at i-1. This is only possible if i-x >= 0.
    6. The final answer is dp[n-x+1][k].

Walkthrough

Detailed Steps:

  1. Pre-calculate Subarray Costs: We create a costs array to store the cost for each potential subarray. For every starting index i from 0 to n-x, we consider the subarray nums[i...i+x-1]. The minimum operations to make all elements in this subarray equal is to change them all to the subarray's median. We find the median by sorting a copy of the subarray. The cost is the sum of absolute differences between each element and the median. This process is repeated for all n-x+1 possible subarrays.

    private long calculateCost(int[] nums, int start, int x) {    int[] sub = new int[x];    System.arraycopy(nums, start, sub, 0, x);    Arrays.sort(sub);    long median = sub[(x - 1) / 2];    long cost = 0;    for (int val : sub) {        cost += Math.abs(val - median);    }    return cost;}
  2. Dynamic Programming: After computing all individual subarray costs, the problem reduces to selecting k non-overlapping entries from the costs array with minimum sum. Let dp[i][j] be the minimum cost to select j non-overlapping subarrays from the first i possible starting positions (costs[0...i-1]).

    The recurrence relation is: dp[i][j] = min(dp[i-1][j], costs[i-1] + dp[i-x][j-1])

    • dp[i-1][j]: This corresponds to the case where we do not select the subarray starting at i-1.
    • costs[i-1] + dp[i-x][j-1]: This corresponds to selecting the subarray starting at i-1. If we do, the previous j-1 subarrays must be chosen from starting positions up to i-1-x to ensure they are non-overlapping.

    The final answer is the value in dp[n-x+1][k].

    // Part of the main functionint m = n - x + 1;long[] costs = new long[m];for (int i = 0; i < m; i++) {    costs[i] = calculateCost(nums, i, x);} long[][] dp = new long[m + 1][k + 1];long INF = Long.MAX_VALUE / 2;for (long[] row : dp) {    Arrays.fill(row, INF);}for (int i = 0; i <= m; i++) {    dp[i][0] = 0;} for (int j = 1; j <= k; j++) {    for (int i = 1; i <= m; i++) {        // Option 1: Don't take subarray starting at i-1        long option1 = dp[i - 1][j];                // Option 2: Take subarray starting at i-1        long option2 = INF;        if (i - x >= 0) {            if (dp[i - x][j - 1] != INF) {                option2 = costs[i - 1] + dp[i - x][j - 1];            }        } else { // This can only be the first subarray chosen            if (j == 1) {                option2 = costs[i - 1];            }        }        dp[i][j] = Math.min(option1, option2);    }}return dp[m][k];

Complexity

Time

O(n * x * log(x) + n * k) - The cost calculation step dominates. There are `O(n)` windows, and for each, we sort `x` elements, taking `O(x log x)`. The DP part takes `O(n*k)`.

Space

O(n*k) - We need `O(n)` space for the `costs` array and `O(n*k)` for the DP table.

Trade-offs

Pros

  • The logic is straightforward and easy to understand.

  • It correctly separates the problem into two distinct subproblems: cost calculation and optimal selection.

Cons

  • The naive cost calculation is very slow, with a time complexity of O(n * x * log(x)), which will result in a 'Time Limit Exceeded' verdict for large x.

Video walkthrough

Newsletter

One sharp idea, every week

System design and interview prep — short enough to finish.

No spam. Unsubscribe anytime.

Practice

Same difficulty — related problems to reinforce the pattern.