Open In App

Split into K subarrays to minimize the maximum sum of all subarrays

Last Updated : 25 Jun, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

Given an array arr[] and a number k, split the given array into k subarrays such that the maximum subarray sum achievable out of k subarrays formed is the minimum possible, find that possible subarray sum.

Examples:

Input: arr[] = [1, 2, 3, 4], k = 3 
Output:
Explanation: Optimal Split is [1, 2], [3], [4]. Maximum sum of all subarrays is 4, which is minimum possible for 3 splits.

Input: arr[] = [1, 1, 2], k = 2 
Output:
Explanation: Splitting the array as [1, 1] and [2] is optimal. This results is a maximum sum subarray of 2.

[Naive Approach] - By iterating through every possible solution

The idea is to recursively try all ways to split the array into k contiguous subarrays, tracking the maximum sum in each split. At each step, we pick a new partition point and update the current max sum. Once only one partition remains, the rest of the elements are grouped, and the overall minimum of the maximum subarray sums is recorded.

C++
#include <iostream>     
#include <vector>       
#include <climits>      
#include <algorithm> 
using namespace std;

void solve(vector<int> &arr, int k, int index, int maxsum, int &ans) {

    // K = 1 is the base Case
    int n = arr.size();
    int sum = 0;
    if (k == 1) {

        for (int i = index; i < n; i++) {

            sum += arr[i];
        }
      
        // we update maxsum
        maxsum = max(maxsum, sum);

        ans = min(ans, maxsum);
        return;
    }

    // using for loop to divide the array into K-subarray
    for (int i = index; i < n; i++) {

        sum += arr[i];
      
        // for each subarray we calculate sum ans update
        // maxsum
        maxsum = max(maxsum, sum);

        solve(arr, k - 1, i + 1, maxsum, ans);
    }
}

int splitArray(vector<int> &arr, int k) {

    int ans = INT_MAX;
    solve(arr, k, 0, 0, ans);
    return ans;
}
int main() {

    vector<int> arr = {1, 2, 3, 4};
    int k = 3;

    cout << splitArray(arr, k);
}
Java
// Java code to iterate through
// every possible solution
import java.util.*;

class GfG {
    static void solve(int[] arr, int k, int index,
                      int maxsum, int[] ans) {

        // K=1 is the base Case
        int n = arr.length;
        int sum = 0;
        if (k == 1) {
            for (int i = index; i < n; i++) {
                sum += arr[i];
            }
          
            // we update maxsum
            maxsum = Math.max(maxsum, sum);
          
            ans[0] = Math.min(ans[0], maxsum);
            return;
        }

        // using for loop to divide the array into
        // K-subarray
        for (int i = index; i < n; i++) {
            sum += arr[i];

            // for each subarray we calculate sum and update
            // maxsum
            maxsum = Math.max(maxsum, sum);
   
            solve(arr, k - 1, i + 1, maxsum, ans);
        }
    }

    static int splitArray(int[] arr, int k) {
        int[] ans = { Integer.MAX_VALUE };
        solve(arr, k, 0, 0, ans);
        return ans[0];
    }

    public static void main(String[] args) {
        int[] arr = { 1, 2, 3, 4 };
        int k = 3;

        System.out.println(splitArray(arr, k));
    }
}
Python
# Python code to iterate through
# every possible solution

def solve(arr, k, index, maxsum, ans):
  
    # K=1 is the base Case
    n = len(arr)
    sum = 0
    if k == 1:
        for i in range(index, n):
            sum += arr[i]
            
        # we update maxsum
        maxsum = max(maxsum, sum)
        
        # the answer is stored in ans
        ans[0] = min(ans[0], maxsum)
        return

    # using for loop to divide the array into K-subarray
    for i in range(index, n):
        sum += arr[i]
        
        # for each subarray we calculate sum and update
        # maxsum
        maxsum = max(maxsum, sum)
        
        solve(arr, k - 1, i + 1, maxsum, ans)


def splitArray(arr, k):
    ans = [float('inf')]
    solve(arr, k, 0, 0, ans)
    return ans[0]


arr = [1, 2, 3, 4]
k = 3

print(splitArray(arr, k))
C#
// C# code to iterate through
// every possible solution
using System;

class GfG {
    static void Solve(int[] arr, int k, int index,
                      int maxsum, ref int ans) {

        // K=1 is the base Case
        int n = arr.Length;
        int sum = 0;
        if (k == 1) {
            for (int i = index; i < n; i++) {
                sum += arr[i];
            }
          
            // we update maxsum
            maxsum = Math.Max(maxsum, sum);
          
            ans = Math.Min(ans, maxsum);
            return;
        }

        // using for loop to divide the array into
        // K-subarray
        for (int i = index; i < n; i++) {
            sum += arr[i];
          
            // for each subarray we calculate sum and update
            // maxsum
            maxsum = Math.Max(maxsum, sum);
          
            Solve(arr, k - 1, i + 1, maxsum, ref ans);
        }
    }

    static int SplitArray(int[] arr, int k) {
        int ans = int.MaxValue;
        Solve(arr, k, 0, 0, ref ans);
        return ans;
    }

    static void Main(string[] args) {
        int[] arr = { 1, 2, 3, 4 };
        int k = 3;

        Console.WriteLine(SplitArray(arr, k));
    }
}
JavaScript
function solve(arr, k, index, maxsum, ans) {

    // K=1 is the base Case
    const n = arr.length;
    let sum = 0;
    if (k === 1) {
        for (let i = index; i < n; i++) {
            sum += arr[i];
        }
        
        // we update maxsum
        maxsum = Math.max(maxsum, sum);

        ans[0] = Math.min(ans[0], maxsum);
        return;
    }

    // using for loop to divide the array into K-subarray
    for (let i = index; i < n; i++) {
        sum += arr[i];
        
        // for each subarray we calculate sum and update
        // maxsum
        maxsum = Math.max(maxsum, sum);
   
        solve(arr, k - 1, i + 1, maxsum, ans);
    }
}

function splitArray(arr, k) {
    let ans = [ Infinity ];
    solve(arr, k, 0, 0, ans);
    return ans[0];
}

// Driver Code
const arr = [ 1, 2, 3, 4 ];
const k = 3;

console.log(splitArray(arr, k));

Output
4

Time Complexity: O((n-1)C(k-1)), to explores all ways to split n elements into k contiguous parts by choosing k-1 split points from n-1 possible positions.
Auxiliary Space: O(k), due to the maximum recursion depth being k, with each call using constant space.

[Expected Approach] Using Binary Search

The approach uses Binary Search to find the minimum possible value for the maximum subarray sum when the array is split into k subarrays. The binary search range is between the maximum element of the array (since no subarray can have a sum less than the largest element) and the total sum of the array (which is the maximum sum when the entire array is considered as a single subarray). For each midpoint value, we check if it's possible to split the array into k or fewer subarrays such that no subarray's sum exceeds the midpoint. If it is possible, we attempt to minimize the maximum sum by narrowing the search range to smaller values.

C++
#include <iostream>      
#include <vector>        
#include <algorithm>
using namespace std;

bool check(int mid, vector<int> &arr, int k) {

    int n = arr.size();
    int count = 0;
    int sum = 0;
    for (int i = 0; i < n; i++) {

        // If individual element is greater
        // maximum possible sum
        if (arr[i] > mid)
            return false;

        // Increase sum of current sub - arr
        sum += arr[i];

        // If the sum is greater than
        // mid increase count
        if (sum > mid) {

            count++;
            sum = arr[i];
        }
    }
    count++;

    if (count <= k)
        return true;
    return false;
}

int splitArray(vector<int> &arr, int k) {

    int n = arr.size();
    int max = *max_element(arr.begin(), arr.end());

    // Max subarr sum, considering subarr of length 1
    int start = max;

    // Max subarr sum, considering subarr of length n
    int end = 0;

    for (int i = 0; i < n; i++) {

        end += arr[i];
    }

    // ans stores possible
    // maximum sub arr sum
    int ans = 0;
    while (start <= end) {

        int mid = (start + end) / 2;

        // If mid is possible solution
        // Put ans = mid;
        if (check(mid, arr, k)) {

            ans = mid;
            end = mid - 1;
        }
        else {
            start = mid + 1;
        }
    }

    return ans;
}

int main() {

    vector<int> arr = {1, 2, 3, 4};
    int k = 3;
    cout << splitArray(arr, k);
}
Java
import java.util.*;

class GfG {

    static boolean check(int mid, int[] arr, int k) {
        int n = arr.length;
        int count = 0;
        int sum = 0;
        for (int i = 0; i < n; i++) {
          
            // If individual element is greater
            // maximum possible sum
            if (arr[i] > mid)
                return false;

            // Increase sum of current sub - arr
            sum += arr[i];

            // If the sum is greater than
            // mid increase count
            if (sum > mid) {
                count++;
                sum = arr[i];
            }
        }
        count++;

        return count <= k;
    }

    static int splitArray(int[] arr, int k) {
        int n = arr.length;
        int max = Arrays.stream(arr).max().getAsInt();

        // Max subarr sum, considering subarr of length 1
        int start = max;

        // Max subarr sum, considering subarr of length n
        int end = 0;

        for (int value : arr) {
            end += value;
        }

        // ans stores possible
        // maximum sub arr sum
        int ans = 0;
        while (start <= end) {
            int mid = (start + end) / 2;

            // If mid is possible solution
            // Put ans = mid;
            if (check(mid, arr, k)) {
                ans = mid;
                end = mid - 1;
            }
            else {
                start = mid + 1;
            }
        }

        return ans;
    }

    public static void main(String[] args) {
        int[] arr = { 1, 2, 3, 4 };
        int k = 3;
        System.out.println(splitArray(arr, k));
    }
}
Python
def check(mid, arr, k):
    n = len(arr)
    count = 0
    total = 0
    for num in arr:
      
        # If individual element is greater
        # maximum possible sum
        if num > mid:
            return False

        # Increase sum of current sub-array
        total += num

        # If the sum is greater than mid, increase count
        if total > mid:
            count += 1
            total = num
    count += 1

    return count <= k


def splitArray(arr, k):
    n = len(arr)
    start = max(arr)
    end = sum(arr)    

    # ans stores possible maximum subarray sum
    ans = 0
    while start <= end:
        mid = (start + end) // 2

        # If mid is possible solution, set ans = mid
        if check(mid, arr, k):
            ans = mid
            end = mid - 1
        else:
            start = mid + 1

    return ans


arr = [1, 2, 3, 4]
k = 3
print(splitArray(arr, k))
C#
using System;
using System.Linq;

class GfG {

    static bool Check(int mid, int[] arr, int k) {
        int n = arr.Length;
        int count = 0;
        int sum = 0;
        for (int i = 0; i < n; i++) {
          
            // If individual element is greater
            // maximum possible sum
            if (arr[i] > mid)
                return false;

            // Increase sum of current sub-array
            sum += arr[i];

            // If the sum is greater than mid, increase
            // count
            if (sum > mid) {
                count++;
                sum = arr[i];
            }
        }
        count++;
      
        return count <= k;
    }

    static int SplitArray(int[] arr, int k) {
        int n = arr.Length;
        int start = arr.Max();
        int end = 0;

        foreach(int num in arr) { end += num; }

        // ans stores possible maximum subarray sum
        int ans = 0;
        while (start <= end) {
            int mid = (start + end) / 2;

            // If mid is possible solution, set ans = mid
            if (Check(mid, arr, k)) {
                ans = mid;
                end = mid - 1;
            }
            else {
                start = mid + 1;
            }
        }

        return ans;
    }

    static void Main() {
        int[] arr = { 1, 2, 3, 4 };
        int k = 3;

        Console.WriteLine(SplitArray(arr, k));
    }
}
JavaScript
function check(mid, arr, k) {
    const n = arr.length;
    let count = 0;
    let sum = 0;

    for (let i = 0; i < n; i++) {
    
        // If individual element is greater
        // maximum possible sum
        if (arr[i] > mid) {
            return false;
        }

        // Increase sum of current sub-array
        sum += arr[i];

        // If the sum is greater than mid, increase count
        if (sum > mid) {
            count++;
            sum = arr[i];
        }
    }
    count++;

    return count <= k;
}

function splitArray(arr, k) {

    const n = arr.length;
    let start
        = Math.max(...arr);
    let end
        = arr.reduce((a, b) => a + b,
                     0);

    // ans stores possible maximum subarray sum
    let ans = 0;
    while (start <= end) {
        const mid = Math.floor((start + end) / 2);

        // If mid is possible solution, set ans = mid
        if (check(mid, arr, k)) {
            ans = mid;
            end = mid - 1;
        }
        else {
            start = mid + 1;
        }
    }

    return ans;
}

// Driver Code
const arr = [ 1, 2, 3, 4 ];
const k = 3;

console.log(splitArray(arr, k));

Output
4

Time Complexity: O(n * log(sum)), where n is the array size and sum is the total sum of the array, due to binary search from max(arr) to sum(arr) and linear checking in each iteration.
Auxiliary Space: O(1), uses constant extra space regardless of input size (excluding input and output storage).



Next Article

Similar Reads