K maximum sums of overlapping contiguous sub-arrays
Last Updated :
29 Mar, 2024
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 array
vector<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 cand
void 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 needed
void 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 sums
void 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 Program
int 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 array
def 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 cand
def 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 needed
def 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 sums
def 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 1
arr1 = [4, -8, 9, -4, 1, -8, -1, 6]
k1 = 4
kMaxOvSubArray(arr1, k1)
# Test case 2
arr2 = [-2, -3, 4, -1, -2, 1, 5, -3]
k2 = 3
kMaxOvSubArray(arr2, k2)
JavaScript
<script>
// Javascript program to find out k maximum sum of overlapping sub-arrays
// Function to compute prefix-sum of the input array
function 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 cand
function 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 needed
function 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 sums
function 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 1
arr1 = [4, -8, 9, -4, 1, -8, -1, 6];
k1 = 4;
kMaxOvSubArray(arr1, k1);
// Test case 2
arr2 = [-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-arrays
using 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] + " ");
}
}
}
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)
Similar Reads
K maximum sums of non-overlapping contiguous sub-arrays
Given an Array of Integers and an Integer value k, find out k non-overlapping sub-arrays which have k maximum sums. Examples: Input : arr1[] = {4, 1, 1, -1, -3, -5, 6, 2, -6, -2}, k = 3. Output : {4,1},{1} and {6,2} can be taken, thus the output should be 14. Input : arr2 = {5, 1, 2, -6, 2, -1, 3, 1
10 min read
Maximum sum of at most K non-overlapping Subarray
Given an array, arr[] of size N, the task is to find the sum of the at most K non-overlapping contiguous subarray within an arr[] with the maximum sum. Examples: Input: arr[] = [4, 1, -3, 7, -5, 6, -2, 1], K = 3Output: 18Explanation: In the above input, the maximum k subarray sum is 18 and the subar
15 min read
Maximize count of non-overlapping subarrays with sum K
Given an array arr[] and an integer K, the task is to print the maximum number of non-overlapping subarrays with a sum equal to K. Examples: Input: arr[] = {-2, 6, 6, 3, 5, 4, 1, 2, 8}, K = 10Output: 3Explanation: All possible non-overlapping subarrays with sum K(= 10) are {-2, 6, 6}, {5, 4, 1}, {2,
6 min read
Count maximum non-overlapping subarrays with given sum
Given an array arr[] consisting of N integers and an integer target, the task is to find the maximum number of non-empty non-overlapping subarrays such that the sum of array elements in each subarray is equal to the target. Examples: Input: arr[] = {2, -1, 4, 3, 6, 4, 5, 1}, target = 6Output: 3Expla
7 min read
Maximum sum of non-overlapping subarrays of length atmost K
Given an integer array 'arr' of length N and an integer 'k', select some non-overlapping subarrays such that each sub-array if of length at most 'k', no two sub-arrays are adjacent and sum of all the elements of the selected sub-arrays are maximum.Examples: Input : arr[] = {-1, 2, -3, 4, 5}, k = 2 O
10 min read
Maximum non overlapping Subset with sum greater than K
Given an array, arr[] and integer K, the task is to find the maximum number of non-overlapping subsets such that the sum of the subsets is strictly greater than K when you may also change the value of each element to the maximum value of the particular subset. Examples: Input: arr[]= {90, 80, 70, 60
5 min read
Maximum Sum of two non-overlapping Subarrays of any length
Given an array A consisting of N integers, the task is to find the maximum sum of two non-overlapping subarrays of any length of the array. Note: You can select empty subarrays also. Examples: Input: N = 3, A[] = {-4, -5, -2}Output: 0Explanation: Two empty subarrays are optimal with maximum sum = 0.
6 min read
Queries to find maximum sum contiguous subarrays of given length in a rotating array
Given an array arr[] of N integers and Q queries of the form {X, Y} of the following two types: If X = 1, rotate the given array to the left by Y positions.If X = 2, print the maximum sum subarray of length Y in the current state of the array. Examples: Input: N = 5, arr[] = {1, 2, 3, 4, 5}, Q = 2,
13 min read
Maximise array sum after taking non-overlapping sub-arrays of length K
Given an integer array arr[] of length N and an integer K, the task is to select some non-overlapping sub-arrays such that each sub-array is exactly of length K, no two sub-arrays are adjacent and sum of all the elements of the selected sub-arrays is maximum.Examples: Input: arr[] = {1, 2, 3, 4, 5},
8 min read
Maximum absolute difference between sum of two contiguous sub-arrays
Given an array of integers, find two non-overlapping contiguous sub-arrays such that the absolute difference between the sum of two sub-arrays is maximum. Example: Input: [-2, -3, 4, -1, -2, 1, 5, -3] Output: 12 Two subarrays are [-2, -3] and [4, -1, -2, 1, 5] Input: [2, -1, -2, 1, -4, 2, 8] Output:
15+ min read