Given an array of Integers and an Integer value k, find out k sub-arrays(may be overlapping), which have k maximum sums. Examples:
Input : arr = {4, -8, 9, -4, 1, -8, -1, 6}, k = 4
Output : 9 6 6 5
Input : arr = {-2, -3, 4, -1, -2, 1, 5, -3}, k= 3
Output : 7 6 5
Using Kadane’s Algorithm we can find the maximum contiguous subarray sum of an array. But in the case Kadane’s Algorithm does not work. As whenever we hit an negative number in the array we set the max_ending_here variable to zero, hence we miss the possibilities for second and so on maximums. Here we use an algorithm presented by Sung Eun Bae and Tadao Takaoka which computes the maximum sub-array sum problem in O(n) time and k maximum sub-array sum problem in O(k*n) time. First we look at the problem of only maximum sub-array sum using this method: Prerequisite: 1. Prefix sum array 2. Maximum subarray sum in O(n) using prefix sum Method for k-maximum sub-arrays:
1. Calculate the prefix sum of the input array.
2. Take cand, maxi and mini as arrays of size k.
3. Initialize mini[0] = 0 for the same reason as previous.
4. for each value of the prefix_sum[i] do
(i). update cand[j] value by prefix_sum[i] - mini[j]
(ii). maxi will be the maximum k elements of maxi and cand
(iii). if prefix_sum is less than all values of mini, then
include it in mini and remove the maximum element from mini
// After the ith iteration mini holds k minimum prefix sum upto
// index i and maxi holds k maximum overlapping sub-array sums
// upto index i.
5. return maxi
Throughout this calculation method, we keep maxi in non-increasing and mini in non-decreasing order.Â
C++
// C++ program to find out k maximum sum of// overlapping sub-arrays#include <iostream>#include <limits>#include <vector>Â
using namespace std;Â
// Function to compute prefix-sum of the input arrayvector<int> prefix_sum(vector<int> arr, int n){Â Â Â Â vector<int> pre_sum;Â Â Â Â pre_sum.push_back(arr[0]);Â Â Â Â for (int i = 1; i < n; i++) Â Â Â Â Â Â Â Â pre_sum.push_back(pre_sum[i - 1] + arr[i]);Â Â Â Â Â Â Â return pre_sum;}Â
// Update maxi by k maximum values from maxi and candvoid maxMerge(vector<int>& maxi, vector<int> cand){    // Here cand and maxi arrays are in non-increasing    // order beforehand. Now, j is the index of the    // next cand element and i is the index of next    // maxi element. Traverse through maxi array.    // If cand[j] > maxi[i] insert cand[j] at the ith    // position in the maxi array and remove the minimum    // element of the maxi array i.e. the last element    // and increase j by 1 i.e. take the next element    // from cand.    int k = maxi.size();    int j = 0;    for (int i = 0; i < k; i++) {        if (cand[j] > maxi[i]) {            maxi.insert(maxi.begin() + i, cand[j]);            maxi.erase(maxi.begin() + k);            j += 1;        }    }}Â
// Insert prefix_sum[i] to mini array if neededvoid insertMini(vector<int>& mini, int pre_sum){    // Traverse the mini array from left to right.    // If prefix_sum[i] is less than any element    // then insert prefix_sum[i] at that position    // and delete maximum element of the mini array    // i.e. the rightmost element from the array.    int k = mini.size();    for (int i = 0; i < k; i++) {        if (pre_sum < mini[i]) {            mini.insert(mini.begin() + i, pre_sum);            mini.erase(mini.begin() + k);            break;        }    }}Â
// Function to compute k maximum overlapping sub-// array sumsvoid kMaxOvSubArray(vector<int> arr, int k){Â Â Â Â int n = arr.size();Â
    // Compute the prefix sum of the input array.    vector<int> pre_sum = prefix_sum(arr, n);Â
    // Set all the elements of mini as +infinite    // except 0th. Set the 0th element as 0.    vector<int> mini(k, numeric_limits<int>::max());    mini[0] = 0;Â
    // Set all the elements of maxi as -infinite.    vector<int> maxi(k, numeric_limits<int>::min());Â
    // Initialize cand array.    vector<int> cand(k);Â
    // For each element of the prefix_sum array do:    // compute the cand array.    // take k maximum values from maxi and cand    // using maxmerge function.    // insert prefix_sum[i] to mini array if needed    // using insertMini function.    for (int i = 0; i < n; i++) {        for (int j = 0; j < k; j++) {             if(pre_sum[i] < 0 && mini[j]==numeric_limits<int>::max())           cand[j]=(-pre_sum[i])-mini[j];         else cand[j] = pre_sum[i] - mini[j];        }        maxMerge(maxi, cand);        insertMini(mini, pre_sum[i]);    }Â
    // Elements of maxi array is the k    // maximum overlapping sub-array sums.    // Print out the elements of maxi array.    for (int ele : maxi)        cout << ele << " ";    cout << endl;}Â
// Driver Programint main(){Â Â Â Â // Test case 1Â Â Â Â vector<int> arr1 = { 4, -8, 9, -4, 1, -8, -1, 6 };Â Â Â Â int k1 = 4;Â Â Â Â kMaxOvSubArray(arr1, k1);Â
    // Test case 2    vector<int> arr2 = { -2, -3, 4, -1, -2, 1, 5, -3 };    int k2 = 3;    kMaxOvSubArray(arr2, k2);    return 0;} |
Java
// Java program to find out k maximum sum of// overlapping sub-arraysÂ
import java.util.ArrayList;Â
class KthMaxSumOverlappingListVersion {Â Â Â Â public static void main(String[] args)Â Â Â Â {Â Â Â Â Â Â Â Â int[] ab = { 4, -8, 9, -4, 1, -8, -1, 6 };Â Â Â Â Â Â Â Â int[] aa = { -2, -3, 4, -1, -2, 1, 5, -3 };Â Â Â Â Â Â Â Â Â Â kthMaxSumOverlapping(ab, ab.length, 4);Â Â Â Â Â Â Â Â Â Â System.out.println();Â Â Â Â Â Â Â Â kthMaxSumOverlapping(aa, aa.length, 3);Â Â Â Â }Â
    // Here cand and maxi arrays are in non-increasing    // order beforehand. Now, j is the index of the    // next cand element and i is the index of next    // maxi element. Traverse through maxi array.    // If cand[j] > maxi[i] insert cand[j] at the ith    // position in the maxi array and remove the minimum    // element of the maxi array i.e. the last element    // and increase j by 1 i.e. take the next element    // from cand.    static void maxMerge(ArrayList<Integer> max,                         ArrayList<Integer> cand)    {        int k = max.size();        int j = 0;        for (int i = 0; i < k; i++) {            if (cand.get(j) > max.get(i)) {                max.add(i, cand.get(j));                max.remove(k);                j++;            }        }    }Â
    // Traverse the mini array from left to right.    // If prefix_sum[i] is less than any element    // then insert prefix_sum[i] at that position    // and delete maximum element of the min    // i.e. the rightmost element from the min.    static void minMerge(ArrayList<Integer> min, int ms)    {        for (int i = 0; i < min.size(); i++) {            if (min.get(i) > ms) {                min.add(i, ms);                min.remove(min.size() - 1);                break;            }        }    }Â
    static void kthMaxSumOverlapping(int[] aa, int n, int k)    {        ArrayList<Integer> max = new ArrayList<Integer>();        ArrayList<Integer> min = new ArrayList<Integer>();        ArrayList<Integer> cand = new ArrayList<Integer>();        int[] prefixSum = new int[n];        prefixSum[0] = aa[0];        for (int i = 1; i < n; i++)            prefixSum[i] = prefixSum[i - 1] + aa[i];        for (int i = 0; i < k; i++) {            max.add(Integer.MIN_VALUE);            min.add(Integer.MAX_VALUE);        }        min.add(0, 0);        min.remove(k);        for (int i = 0; i < n; i++) {            for (int j = 0; j < k; j++) {                cand.add(prefixSum[i] - min.get(j));            }            maxMerge(max, cand);            minMerge(min, prefixSum[i]);            cand.clear();        }Â
        for (int i = 0; i < k; i++) {            System.out.print(max.get(i) + " ");        }    }} |
Python3
# Python program to find out k maximum sum of# overlapping sub-arraysÂ
# Function to compute prefix-sum of the input arraydef prefix_sum(arr, n):Â Â Â Â pre_sum = list()Â Â Â Â pre_sum.append(arr[0])Â Â Â Â for i in range(1, n):Â Â Â Â Â Â Â Â pre_sum.append(pre_sum[i-1] + arr[i])Â Â Â Â return pre_sumÂ
# Update maxi by k maximum values from maxi and canddef maxMerge(maxi, cand):Â
    # Here cand and maxi arrays are in non-increasing    # order beforehand. Now, j is the index of the    # next cand element and i is the index of next    # maxi element. Traverse through maxi array.    # If cand[j] > maxi[i] insert cand[j] at the ith    # position in the maxi array and remove the minimum    # element of the maxi array i.e. the last element    # and increase j by 1 i.e. take the next element    # from cand.    k = len(maxi)    j = 0    for i in range(k):        if (cand[j] > maxi[i]):            maxi.insert(i, cand[j])            del maxi[-1]            j += 1Â
# Insert prefix_sum[i] to mini array if neededdef insertMini(mini, pre_sum):Â
    # Traverse the mini array from left to right.    # If prefix_sum[i] is less than any element    # then insert prefix_sum[i] at that position    # and delete maximum element of the mini array    # i.e. the rightmost element from the array.    k = len(mini)    for i in range(k):        if (pre_sum < mini[i]):            mini.insert(i, pre_sum)            del mini[-1]            breakÂ
# Function to compute k maximum overlapping sub-array sumsdef kMaxOvSubArray(arr, k):Â Â Â Â n = len(arr)Â
    # Compute the prefix sum of the input array.    pre_sum = prefix_sum(arr, n)Â
    # Set all the elements of mini as + infinite    # except 0th. Set the 0th element as 0.    mini = [float('inf') for i in range(k)]    mini[0] = 0Â
    # Set all the elements of maxi as -infinite.    maxi = [-float('inf') for i in range(k)]Â
    # Initialize cand array.    cand = [0 for i in range(k)]Â
    # For each element of the prefix_sum array do:    # compute the cand array.    # take k maximum values from maxi and cand    # using maxmerge function.    # insert prefix_sum[i] to mini array if needed    # using insertMini function.    for i in range(n):        for j in range(k):            cand[j] = pre_sum[i] - mini[j]        maxMerge(maxi, cand)        insertMini(mini, pre_sum[i])Â
    # Elements of maxi array is the k    # maximum overlapping sub-array sums.    # Print out the elements of maxi array.    for ele in maxi:        print(ele, end = ' ')    print('')Â
# Driver Program# Test case 1arr1 = [4, -8, 9, -4, 1, -8, -1, 6]k1 = 4kMaxOvSubArray(arr1, k1)Â
# Test case 2arr2 = [-2, -3, 4, -1, -2, 1, 5, -3]k2 = 3kMaxOvSubArray(arr2, k2) |
Javascript
<script>// Javascript program to find out k maximum sum of overlapping sub-arrays//Â Function to compute prefix-sum of the input arrayfunction prefix_sum(arr, n){Â Â Â Â var pre_sum = [];Â Â Â Â pre_sum.push(arr[0]);Â Â Â Â for(var i = 1; i < n; i++)Â Â Â Â Â Â Â Â pre_sum.push(pre_sum[i-1] + arr[i]);Â Â Â Â return pre_sum;}Â
// Update maxi by k maximum values from maxi and candfunction maxMerge(maxi, cand){Â
    // Here cand and maxi arrays are in non-increasing    // order beforehand. Now, j is the index of the    // next cand element and i is the index of next    // maxi element. Traverse through maxi array.    // If cand[j] > maxi[i] insert cand[j] at the ith    // position in the maxi array and remove the minimum    // element of the maxi array i.e. the last element    // and increase j by 1 i.e. take the next element    // from cand.    var k = maxi.length;    var j = 0;    for(var i = 0; i < k; i++){        if (cand[j] > maxi[i]){            maxi.splice(i,0, cand[j]);            maxi.pop();            j += 1;        }    }}// Insert prefix_sum[i] to mini array if neededfunction insertMini(mini, pre_sum){Â
    // Traverse the mini array from left to right.    // If prefix_sum[i] is less than any element    // then insert prefix_sum[i] at that position    // and delete maximum element of the mini array    // i.e. the rightmost element from the array.    k = mini.length;    for (var i = 0; i < k; i++){        if (pre_sum < mini[i]){            mini.splice(i,0, pre_sum);            mini.pop();            break;        }    }}// Function to compute k maximum overlapping sub-array sumsfunction kMaxOvSubArray(arr, k){    n = arr.length;Â
    // Compute the prefix sum of the input array.    pre_sum = prefix_sum(arr, n);    // console.log(pre_sum);    // Set all the elements of mini as + infinite    // except 0th. Set the 0th element as 0.    mini = [];    for(var i = 0; i < k;i++){        mini.push(Infinity);    }    mini[0] = 0;Â
    // Set all the elements of maxi as -infinite.    maxi = [];    for( i = 0; i < k;i++){        maxi.push(-Infinity);    }Â
    // Initialize cand array.    cand = [];    for( i = 0; i < k;i++){        mini.push(0);    }    // For each element of the prefix_sum array do:    // compute the cand array.    // take k maximum values from maxi and cand    // using maxmerge function.    // insert prefix_sum[i] to mini array if needed    // using insertMini function.    for(i = 0; i < n;i++){        for (var j = 0; j < k ;j++)            cand[j] = pre_sum[i] - mini[j];        maxMerge(maxi, cand);        insertMini(mini, pre_sum[i]);    }    // Elements of maxi array is the k    // maximum overlapping sub-array sums.    // Print out the elements of maxi array.    for( i = 0; i < maxi.length;i++){        document.write(maxi[i]+" ");    }    document.write("\n");}Â
//Â Driver Program// Test case 1arr1 = [4, -8, 9, -4, 1, -8, -1, 6];k1 = 4;kMaxOvSubArray(arr1, k1);Â
//Â Test case 2arr2 = [-2, -3, 4, -1, -2, 1, 5, -3];k2 = 3;kMaxOvSubArray(arr2, k2);Â
// This code is contributed by repakaeswaripriya.</script> |
C#
// c# program to find out k maximum sum of// overlapping sub-arraysusing System;using System.Collections.Generic;Â
class KthMaxSumOverlappingListVersion{static void Main(string[] args){int[] ab = { 4, -8, 9, -4, 1, -8, -1, 6 };int[] aa = { -2, -3, 4, -1, -2, 1, 5, -3 };kthMaxSumOverlapping(ab, ab.Length, 4);Console.WriteLine();kthMaxSumOverlapping(aa, aa.Length, 3);}   // Here cand and maxi arrays are in non-increasing    // order beforehand. Now, j is the index of the    // next cand element and i is the index of next    // maxi element. Traverse through maxi array.    // If cand[j] > maxi[i] insert cand[j] at the ith    // position in the maxi array and remove the minimum    // element of the maxi array i.e. the last element    // and increase j by 1 i.e. take the next element    // from cand.    static void maxMerge(List<int> max, List<int> cand){    int k = max.Count;    int j = 0;    for (int i = 0; i < k; i++)    {        if (cand[j] > max[i])        {            max.Insert(i, cand[j]);            max.RemoveAt(k);            j++;        }    }}// Traverse the mini array from left to right.    // If prefix_sum[i] is less than any element    // then insert prefix_sum[i] at that position    // and delete maximum element of the min    // i.e. the rightmost element from the min.static void minMerge(List<int> min, int ms){    for (int i = 0; i < min.Count; i++)    {        if (min[i] > ms)        {            min.Insert(i, ms);            min.RemoveAt(min.Count - 1);            break;        }    }}Â
static void kthMaxSumOverlapping(int[] aa, int n, int k){Â Â Â Â List<int> max = new List<int>();Â Â Â Â List<int> min = new List<int>();Â Â Â Â List<int> cand = new List<int>();Â Â Â Â int[] prefixSum = new int[n];Â Â Â Â prefixSum[0] = aa[0];Â Â Â Â for (int i = 1; i < n; i++)Â Â Â Â Â Â Â Â prefixSum[i] = prefixSum[i - 1] + aa[i];Â Â Â Â for (int i = 0; i < k; i++)Â Â Â Â {Â Â Â Â Â Â Â Â max.Add(int.MinValue);Â Â Â Â Â Â Â Â min.Add(int.MaxValue);Â Â Â Â }Â Â Â Â min.Insert(0, 0);Â Â Â Â min.RemoveAt(k);Â Â Â Â for (int i = 0; i < n; i++)Â Â Â Â {Â Â Â Â Â Â Â Â for (int j = 0; j < k; j++)Â Â Â Â Â Â Â Â {Â Â Â Â Â Â Â Â Â Â Â Â cand.Add(prefixSum[i] - min[j]);Â Â Â Â Â Â Â Â }Â Â Â Â Â Â Â Â maxMerge(max, cand);Â Â Â Â Â Â Â Â minMerge(min, prefixSum[i]);Â Â Â Â Â Â Â Â cand.Clear();Â Â Â Â }Â Â Â Â for (int i = 0; i < k; i++)Â Â Â Â {Â Â Â Â Â Â Â Â Console.Write(max[i] + " ");Â Â Â Â }}} |
9 6 6 5 7 6 5
Time Complexity: The ‘insertMini’ and ‘maxMerge’ functions runs in O(k) time and it takes O(k) time to update the ‘cand’ array. We do this process for n times. Hence, the overall time complexity is O(k*n).
Auxiliary Space: O(n)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!
