Skip to content
Related Articles

Related Articles

Improve Article
Split array into K subarrays such that sum of maximum of all subarrays is maximized
  • Difficulty Level : Hard
  • Last Updated : 17 Jun, 2021

Given an array arr[] of size N and a number K, the task is to partition the given array into K contiguous subarrays such that the sum of the maximum of each subarray is the maximum possible. If it is possible to split the array in such a manner, then print the maximum possible sum. Otherwise, print “-1“.

Examples:

Input: arr[] = {5, 3, 2, 7, 6, 4}, N = 6, K = 3
Output: 18
              5
              3 2 7
              6 4
Explanation:
One way is to split the array at indices 0, 3 and 4.
Therefore, the subarrays formed are {5}, {3, 2, 7} and {6, 4}.
Therefore, sum of the maximum of each subarray = 5 + 7 + 6 =18 ( which is the maximum possible).

Input: arr[] = {1, 4, 5, 6, 1, 2}, N = 6, K = 2 
Output: 11

Approach: The given problem can be solved using Map data structure and Sorting techniques, based on the following observations: 



  • The maximum obtainable sum would be the sum of the K-largest elements of the array as it is always possible to divide the array into K segments in such a way that the maximum of each segment is one of the K-largest elements.
  • One way would be to break a segment as soon as one of the K-largest element is encountered.

Follow the steps below to solve the problem:

  • First, if N is less than K then print “-1” and then return.
  • Copy array into another array say temp[] and sort the array, temp[] in descending order.
  • Initialize a variable ans to 0, to store the maximum sum possible.
  • Also, Initialize a map say mp, to store the frequency of the K-largest elements.
  • Iterate in the range [0, K-1] using a variable say i, and in each iteration increment the ans by temp[i] and increment the count of temp[i] in map mp.
  • Initialize a vector of vectors say P to store a possible partition and a vector say V to store the elements of a partition.
  • Iterate in the range [0, N-1] and using a variable say i and perform the following steps:
    • Push the current element arr[i] in the vector V.
    • If mp[arr[i]] is greater than 0 then do the following:
      • Decrement K and count of arr[i] in the map mp by 1.
      • If K is equal to 0 i.e it is the last segment then push all the remaining elements of the array arr[] in V.
      • Now push the current segment V in the P.
  • Finally, after completing the above steps, print the maximum sum stores in variable ans and then partition stored in P.

Below is the implementation of the above approach:

C++




// C++ program for tha above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to split the array into K
// subarrays such that the sum of
// maximum of each subarray is maximized
void partitionIntoKSegments(int arr[],
                            int N, int K)
{
    // If N is less than K
    if (N < K) {
        cout << -1 << endl;
        return;
    }
    // Map to store the K
    // largest elements
    map<int, int> mp;
 
    // Auxiliary array to
    // store and sort arr[]
    int temp[N];
 
    // Stores the maximum sum
    int ans = 0;
 
    // Copy arr[] to temp[]
    for (int i = 0; i < N; i++) {
        temp[i] = arr[i];
    }
 
    // Sort array temp[] in
    // descending order
    sort(temp, temp + N,
         greater<int>());
 
    // Iterate in the range [0, K - 1]
    for (int i = 0; i < K; i++) {
 
        // Increment sum by temp[i]
        ans += temp[i];
 
        // Increment count of
        // temp[i] in the map mp
        mp[temp[i]]++;
    }
 
    // Stores the partitions
    vector<vector<int> > P;
 
    // Stores temporary subarrays
    vector<int> V;
 
    // Iterate over the range [0, N - 1]
    for (int i = 0; i < N; i++) {
        V.push_back(arr[i]);
 
        // If current element is
        // one of the K largest
        if (mp[arr[i]] > 0) {
 
            mp[arr[i]]--;
            K--;
 
            if (K == 0) {
                i++;
                while (i < N) {
                    V.push_back(arr[i]);
                    i++;
                }
            }
 
            if (V.size()) {
                P.push_back(V);
                V.clear();
            }
        }
    }
 
    // Print the ans
    cout << ans << endl;
 
    // Print the partition
    for (auto u : P) {
        for (auto x : u)
            cout << x << " ";
        cout << endl;
    }
}
// Driver code
int main()
{
    // Input
    int A[] = { 5, 3, 2, 7, 6, 4 };
    int N = sizeof(A) / sizeof(A[0]);
    int K = 3;
 
    // Function call
    partitionIntoKSegments(A, N, K);
    return 0;
}

Java




// Java program for the above approach
import java.util.*;
public class GFG
{
 
// Function to split the array into K
// subarrays such that the sum of
// maximum of each subarray is maximized
static void partitionIntoKSegments(int arr[], int N, int K)
{
     
    // If N is less than K
    if (N < K)
    {
         System.out.println(-1);
        return;
    }
     
    // Map to store the K
    // largest elements
    HashMap<Integer,Integer> mp = new HashMap<Integer,Integer>();
 
    // Auxiliary array to
    // store and sort arr[]
    Integer []temp = new Integer[N];
 
    // Stores the maximum sum
    int ans = 0;
 
    // Copy arr[] to temp[]
    for(int i = 0; i < N; i++)
    {
        temp[i] = arr[i];
    }
 
    // Sort array temp[] in
    // descending order
    Arrays.sort(temp,Collections.reverseOrder());
    //Array.Reverse(temp);
 
    // Iterate in the range [0, K - 1]
    for(int i = 0; i < K; i++)
    {
         
        // Increment sum by temp[i]
        ans += temp[i];
 
        // Increment count of
        // temp[i] in the map mp
        if (mp.containsKey(temp[i]))
            mp.get(temp[i]++);
        else
            mp.put(temp[i], 1);
    }
 
    // Stores the partitions
    ArrayList<ArrayList<Integer>> P = new ArrayList<ArrayList<Integer>>();
 
    // Stores temporary subarrays
    ArrayList<Integer> V = new ArrayList<Integer>();
 
    // Iterate over the range [0, N - 1]
    for(int i = 0; i < N; i++)
    {
        V.add(arr[i]);
     
        // If current element is
        // one of the K largest
        if (mp.containsKey(arr[i]) && mp.get(arr[i]) > 0)
        {
            mp.get(arr[i]--);
            K--;
 
            if (K == 0)
            {
                i++;
                 
                while (i < N)
                {
                    V.add(arr[i]);
                    i++;
                }
            }
 
            if (V.size() > 0)
            {
                P.add(new ArrayList<Integer>(V));
                V.clear();
            }
        }
    }
 
    // Print the ans
     System.out.println(ans);
     
    // Print the partition
    for (ArrayList<Integer > subList : P)
    {
        for(Integer  item : subList)
        {
              System.out.print(item+" ");
        }
         System.out.println();
    }
}
 
// Driver code
public static void main(String args[])
{
     
    // Input
    int []A = { 5, 3, 2, 7, 6, 4 };
    int N = A.length;
    int K = 3;
 
    // Function call
    partitionIntoKSegments(A, N, K);
}
}
 
// This code is contributed by SoumikMondal

Python3




# Python program for tha above approach
 
# Function to split the array into K
# subarrays such that the sum of
# maximum of each subarray is maximized
def partitionIntoKSegments(arr, N, K):
    # If N is less than K
    if (N < K):
        print(-1)
        return
    # Map to store the K
    # largest elements
    mp = {}
 
    # Auxiliary array to
    # store and sort arr[]
    temp = [0]*N
 
    # Stores the maximum sum
    ans = 0
 
    # Copy arr[] to temp[]
    for i in range(N):
        temp[i] = arr[i]
 
    # Sort array temp[] in
    # descending order
    temp = sorted(temp)[::-1]
 
    # Iterate in the range [0, K - 1]
    for i in range(K):
        # Increment sum by temp[i]
        ans += temp[i]
 
        # Increment count of
        # temp[i] in the map mp
        mp[temp[i]] = mp.get(temp[i], 0) + 1
 
    # Stores the partitions
    P = []
 
    # Stores temporary subarrays
    V = []
 
    # Iterate over the range [0, N - 1]
    for i in range(N):
        V.append(arr[i])
 
        # If current element is
        # one of the K largest
        if (arr[i] in mp):
 
            mp[arr[i]] -= 1
            K -= 1
 
            if (K == 0):
                i += 1
                while (i < N):
                    V.append(arr[i])
                    i += 1
            # print(V)
 
            if (len(V) > 0):
                P.append(list(V))
                V.clear()
 
    # Prthe ans
    print(ans)
 
    # Prthe partition
    for u in P:
        for x in u:
            print(x,end=" ")
        print()
# Driver code
if __name__ == '__main__':
    # Input
    A = [5, 3, 2, 7, 6, 4]
    N = len(A)
    K = 3
 
    # Function call
    partitionIntoKSegments(A, N, K)
 
# This code is contributed by mohit kumar 29.

C#




// C# program for tha above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function to split the array into K
// subarrays such that the sum of
// maximum of each subarray is maximized
static void partitionIntoKSegments(int []arr,
                                   int N, int K)
{
     
    // If N is less than K
    if (N < K)
    {
        Console.WriteLine(-1);
        return;
    }
     
    // Map to store the K
    // largest elements
    Dictionary<int,
               int> mp = new Dictionary<int,
                                        int>();
 
    // Auxiliary array to
    // store and sort arr[]
    int []temp = new int[N];
 
    // Stores the maximum sum
    int ans = 0;
 
    // Copy arr[] to temp[]
    for(int i = 0; i < N; i++)
    {
        temp[i] = arr[i];
    }
 
    // Sort array temp[] in
    // descending order
    Array.Sort(temp);
    Array.Reverse(temp);
 
    // Iterate in the range [0, K - 1]
    for(int i = 0; i < K; i++)
    {
         
        // Increment sum by temp[i]
        ans += temp[i];
 
        // Increment count of
        // temp[i] in the map mp
        if (mp.ContainsKey(temp[i]))
            mp[temp[i]]++;
        else
            mp.Add(temp[i],1);
    }
 
    // Stores the partitions
    List<List<int>> P = new List<List<int>>();
 
    // Stores temporary subarrays
    List<int> V = new List<int>();
 
    // Iterate over the range [0, N - 1]
    for(int i = 0; i < N; i++)
    {
        V.Add(arr[i]);
     
        // If current element is
        // one of the K largest
        if (mp.ContainsKey(arr[i]) && mp[arr[i]] > 0)
        {
            mp[arr[i]]--;
            K--;
 
            if (K == 0)
            {
                i++;
                 
                while (i < N)
                {
                    V.Add(arr[i]);
                    i++;
                }
            }
 
            if (V.Count > 0)
            {
                P.Add(new List<int>(V));
                V.Clear();
            }
        }
    }
 
    // Print the ans
    Console.WriteLine(ans);
     
    // Print the partition
    foreach (List<int> subList in P)
    {
        foreach (int item in subList)
        {
            Console.Write(item+" ");
        }
        Console.WriteLine();
    }
}
 
// Driver code
public static void Main()
{
     
    // Input
    int []A = { 5, 3, 2, 7, 6, 4 };
    int N = A.Length;
    int K = 3;
 
    // Function call
    partitionIntoKSegments(A, N, K);
}
}
 
// This code is contributed by SURENDRA_GANGWAR

Javascript




<script>
// Javascript program for tha above approach
 
// Function to split the array into K
// subarrays such that the sum of
// maximum of each subarray is maximized
function partitionIntoKSegments(arr, N, K)
{
 
    // If N is less than K
    if (N < K) {
        document.write(-1 + "<br>");
        return;
    }
     
    // Map to store the K
    // largest elements
    let mp = new Map();
 
    // Auxiliary array to
    // store and sort arr[]
    let temp = new Array(N);
 
    // Stores the maximum sum
    let ans = 0;
 
    // Copy arr[] to temp[]
    for (let i = 0; i < N; i++) {
        temp[i] = arr[i];
    }
 
    // Sort array temp[] in
    // descending order
    temp.sort((a, b) => a - b).reverse();
 
    // Iterate in the range [0, K - 1]
    for (let i = 0; i < K; i++) {
 
        // Increment sum by temp[i]
        ans += temp[i];
 
        // Increment count of
        // temp[i] in the map mp
        if (mp.has(temp[i])) {
            mp.set(temp[i], mp.get(temp[i]) + 1)
        } else {
            mp.set(temp[i], 1)
        }
    }
 
    // Stores the partitions
    let P = [];
 
    // Stores temporary subarrays
    let V = [];
 
    // Iterate over the range [0, N - 1]
    for (let i = 0; i < N; i++) {
        V.push(arr[i]);
 
        // If current element is
        // one of the K largest
        if (mp.get(arr[i]) > 0)
        {
 
            mp.set(arr[i], mp.get(arr[i]) - 1)
            K--;
 
            if (K == 0) {
                i++;
                while (i < N) {
                    V.push(arr[i]);
                    i++;
                }
            }
 
            if (V.length) {
                P.push(V);
                V = [];
            }
        }
    }
 
    // Print the ans
    document.write(ans + "<br>");
 
    // Print the partition
    for (let u of P) {
        for (let x of u)
            document.write(x + " ");
        document.write("<br>");
    }
}
 
// Driver code
// Input
let A = [5, 3, 2, 7, 6, 4];
let N = A.length
let K = 3;
 
// Function call
partitionIntoKSegments(A, N, K);
 
// This code is contributed by sanjoy_62.
</script>
Output: 
18
5 
3 2 7 
6 4

 

Time Complexity: O(N*log(N))
Auxiliary Space: O(N)

 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with industry experts, please refer Geeks Classes Live 




My Personal Notes arrow_drop_up
Recommended Articles
Page :