Open In App

Maximizing difference in partitioned Subarrays

Given array numbers[] and a value limit, the task is to partition the array into subarrays such that the size of each subarray ranges from 1 to limit, so as to obtain the maximum difference between minimum and maximum partition.

Examples:

Input: numbers = [1, 2, 3, 4, 5, 6], limit = 3
Output: 12
Explanation: Here the maximum sum after partitioning the array as [1, 2, 3] and [4, 5, 6] is 27 and the minimum sum after partitioning the array as [1, 2, 3] and [4, 5, 6] is 15, the difference obtained is 12.



Input: numbers = [3, 7, 2, 2, 6], limit = 2
Output: 18
Explanation: Here the maximum sum after partitioning the array as [3], [7, 2], and [2, 6] is 29 and the minimum sum after partitioning the array as [3],[7, 2] and [2, 6] is 11, the difference obtained is 18.

Approach: To solve the problem follow the below idea:



For maximum partition:

For minimum partition:

At the end Calculate the difference between the maximum and minimum sums and print it.

Below is the implementation of the above approach:




// C++ code for the above approach:
#include <bits/stdc++.h>
using namespace std;
 
int maxSumAfterPartitioning(vector<int>& arr, int k)
{
 
    // Get the size of the array
    int n = arr.size();
 
    // Initialize a dp vector of size n+1 to
    // prevent access to unallocated memory
    // while updating the curr_sum
    vector<int> dp(n + 1, 0);
 
    // Loop through the array in reverse
    for (int s = n - 1; s >= 0; s--) {
        // Initialize current sum and maximum
        // element with very small values
        int curr_sum = INT_MIN;
        int max_ele = INT_MIN;
 
        // Loop through the next k elements or
        // until the end of the array
        for (int i = s; i < min(s + k, n); i++) {
 
            // Update maximum element
            max_ele = max(max_ele, arr[i]);
 
            // Update current sum
            curr_sum
                = max(curr_sum,
                      dp[i + 1] + max_ele * (i - s + 1));
        }
 
        // Update the dp vector
        dp[s] = curr_sum;
    }
 
    // Return the maximum sum
    return dp[0];
}
 
int minSumAfterPartitioning(vector<int>& arr, int k)
{
    // Get the size of the array
    int n = arr.size();
 
    // Initialize a dp vector of size n+1 to
    // prevent access to unallocated memory
    // while updating the curr_sum
    vector<int> dp(n + 1, 0);
 
    // Loop through the array in reverse
    for (int s = arr.size() - 1; s >= 0; s--) {
        // Initialize current sum and minimum
        // element with very large values
        int curr_sum = INT_MAX;
        int min_ele = INT_MAX;
 
        // Loop through the next k elements or
        // until the end of the array
        for (int i = s; i < min(s + k, n); i++) {
 
            // Update minimum element
            min_ele = min(min_ele, arr[i]);
 
            // Update current sum
            curr_sum
                = min(curr_sum,
                      dp[i + 1] + min_ele * (i - s + 1));
        }
 
        // Update the dp vector
        dp[s] = curr_sum;
    }
 
    // Return the minimum sum
    return dp[0];
}
 
// Drivers code
int main()
{
    vector<int> arr = { 3, 7, 2, 2, 6 };
    int k = 2;
 
    // Print the difference between
    // max and min sums
    cout << maxSumAfterPartitioning(arr, k)
                - minSumAfterPartitioning(arr, k);
    return 0;
}




import java.util.Arrays;
 
public class PartitionArrayMaxMinDifference {
     
    // Function to find the maximum sum after partitioning the array
    public static int maxSumAfterPartitioning(int[] arr, int k) {
        int n = arr.length;
        int[] dp = new int[n + 1];
         
        // Loop through the array in reverse
        for (int s = n - 1; s >= 0; s--) {
            int currSum = Integer.MIN_VALUE;
            int maxElement = Integer.MIN_VALUE;
             
            // Loop through the next k elements or until the end of the array
            for (int i = s; i < Math.min(s + k, n); i++) {
                maxElement = Math.max(maxElement, arr[i]);
                currSum = Math.max(currSum, dp[i + 1] + maxElement * (i - s + 1));
            }
             
            // Update the dp vector
            dp[s] = currSum;
        }
         
        // Return the maximum sum
        return dp[0];
    }
     
    // Function to find the minimum sum after partitioning the array
    public static int minSumAfterPartitioning(int[] arr, int k) {
        int n = arr.length;
        int[] dp = new int[n + 1];
         
        // Loop through the array in reverse
        for (int s = n - 1; s >= 0; s--) {
            int currSum = Integer.MAX_VALUE;
            int minElement = Integer.MAX_VALUE;
             
            // Loop through the next k elements or until the end of the array
            for (int i = s; i < Math.min(s + k, n); i++) {
                minElement = Math.min(minElement, arr[i]);
                currSum = Math.min(currSum, dp[i + 1] + minElement * (i - s + 1));
            }
             
            // Update the dp vector
            dp[s] = currSum;
        }
         
        // Return the minimum sum
        return dp[0];
    }
 
    public static void main(String[] args) {
        int[] arr = {3, 7, 2, 2, 6};
        int k = 2;
 
        // Calculate the maximum and minimum sums after partitioning
        int maxSum = maxSumAfterPartitioning(arr, k);
        int minSum = minSumAfterPartitioning(arr, k);
         
        // Calculate and print the difference between max and min sums
        int difference = maxSum - minSum;
        System.out.println(difference);
    }
}




# Function to calculate the maximum sum after partitioning the array
def maxSumAfterPartitioning(arr, k):
    n = len(arr)
    dp = [0] * (n + 1)
 
    # Loop through the array in reverse
    for s in range(n - 1, -1, -1):
        curr_sum = float('-inf'# Initialize current sum
        max_ele = float('-inf')   # Initialize maximum element
 
        # Loop through the next k elements or until the end of the array
        for i in range(s, min(s + k, n)):
            max_ele = max(max_ele, arr[i])  # Update maximum element
            curr_sum = max(curr_sum, dp[i + 1] + max_ele * (i - s + 1))  # Update current sum
 
        dp[s] = curr_sum  # Update the dp vector
 
    return dp[0# Return the maximum sum
 
# Function to calculate the minimum sum after partitioning the array
def minSumAfterPartitioning(arr, k):
    n = len(arr)
    dp = [0] * (n + 1)
 
    # Loop through the array in reverse
    for s in range(n - 1, -1, -1):
        curr_sum = float('inf'# Initialize current sum
        min_ele = float('inf')   # Initialize minimum element
 
        # Loop through the next k elements or until the end of the array
        for i in range(s, min(s + k, n)):
            min_ele = min(min_ele, arr[i])  # Update minimum element
            curr_sum = min(curr_sum, dp[i + 1] + min_ele * (i - s + 1))  # Update current sum
 
        dp[s] = curr_sum  # Update the dp vector
 
    return dp[0# Return the minimum sum
 
# Driver code
arr = [3, 7, 2, 2, 6]
k = 2
 
# Print the difference between max and min sums
print(maxSumAfterPartitioning(arr, k) - minSumAfterPartitioning(arr, k))




using System;
 
class PartitionArrayMaxMinDifference
{
    // Function to find the maximum sum after partitioning the array
    public static int MaxSumAfterPartitioning(int[] arr, int k)
    {
        int n = arr.Length;
        int[] dp = new int[n + 1];
 
        // Loop through the array in reverse
        for (int s = n - 1; s >= 0; s--)
        {
            int currSum = int.MinValue;
            int maxElement = int.MinValue;
 
            // Loop through the next k elements or until the end of the array
            for (int i = s; i < Math.Min(s + k, n); i++)
            {
                maxElement = Math.Max(maxElement, arr[i]);
                currSum = Math.Max(currSum, dp[i + 1] + maxElement * (i - s + 1));
            }
 
            // Update the dp array
            dp[s] = currSum;
        }
 
        // Return the maximum sum
        return dp[0];
    }
 
    // Function to find the minimum sum after partitioning the array
    public static int MinSumAfterPartitioning(int[] arr, int k)
    {
        int n = arr.Length;
        int[] dp = new int[n + 1];
 
        // Loop through the array in reverse
        for (int s = n - 1; s >= 0; s--)
        {
            int currSum = int.MaxValue;
            int minElement = int.MaxValue;
 
            // Loop through the next k elements or until the end of the array
            for (int i = s; i < Math.Min(s + k, n); i++)
            {
                minElement = Math.Min(minElement, arr[i]);
                currSum = Math.Min(currSum, dp[i + 1] + minElement * (i - s + 1));
            }
 
            // Update the dp array
            dp[s] = currSum;
        }
 
        // Return the minimum sum
        return dp[0];
    }
 
    public static void Main(string[] args)
    {
        int[] arr = { 3, 7, 2, 2, 6 };
        int k = 2;
 
        // Calculate the maximum and minimum sums after partitioning
        int maxSum = MaxSumAfterPartitioning(arr, k);
        int minSum = MinSumAfterPartitioning(arr, k);
 
        // Calculate and print the difference between max and min sums
        int difference = maxSum - minSum;
        Console.WriteLine(difference);
    }
}




// Javascript code for the above approach
 
function maxSumAfterPartitioning(arr, k) {
    // Get the size of the array
    let n = arr.length;
     
    // Initialize a dp array of size n+1 to
    // prevent access to unallocated memory
    // while updating the curr_sum
    let dp = new Array(n + 1).fill(0);
     
    // Loop through the array in reverse
    for (let s = n - 1; s >= 0; s--) {
        // Initialize current sum and maximum
        // element with very small values
        let curr_sum = Number.MIN_SAFE_INTEGER;
        let max_ele = Number.MIN_SAFE_INTEGER;
         
        // Loop through the next k elements or
        // until the end of the array
        for (let i = s; i < Math.min(s + k, n); i++) {
             
            // Update maximum element
            max_ele = Math.max(max_ele, arr[i]);
             
            // Update current sum
            curr_sum = Math.max(curr_sum, dp[i + 1] + max_ele * (i - s + 1));
        }
         
        // Update the dp array
        dp[s] = curr_sum;
    }
     
    // Return the maximum sum
    return dp[0];
}
 
function minSumAfterPartitioning(arr, k) {
    // Get the size of the array
    let n = arr.length;
     
    // Initialize a dp array of size n+1 to
    // prevent access to unallocated memory
    // while updating the curr_sum
    let dp = new Array(n + 1).fill(0);
     
    // Loop through the array in reverse
    for (let s = arr.length - 1; s >= 0; s--) {
        // Initialize current sum and minimum
        // element with very large values
        let curr_sum = Number.MAX_SAFE_INTEGER;
        let min_ele = Number.MAX_SAFE_INTEGER;
         
        // Loop through the next k elements or
        // until the end of the array
        for (let i = s; i < Math.min(s + k, n); i++) {
             
            // Update minimum element
            min_ele = Math.min(min_ele, arr[i]);
             
            // Update current sum
            curr_sum = Math.min(curr_sum, dp[i + 1] + min_ele * (i - s + 1));
        }
        // Update the dp array
        dp[s] = curr_sum;
    }
     
    // Return the minimum sum
    return dp[0];
}
 
// Drivers code
let arr = [3, 7, 2, 2, 6];
let k = 2;
 
// Print the difference between
// max and min sums
console.log(maxSumAfterPartitioning(arr, k) - minSumAfterPartitioning(arr, k));

Output
18








Time Complexity: O(n*k), where “n” is the size of the input array arr, k is the limit.
Auxiliary Space: O(n) due to the dynamic programming vector dp created in both functions.


Article Tags :