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: 16 Two subarrays are [-1, -2, 1, -4] and [2, 8]
Expected time complexity is O(n).
The idea is for each index i in given array arr[0…n-1], compute maximum and minimum sum subarrays that lie in subarrays arr[0…i] and arr[i+1 …n-1]. We maintain four arrays that store the maximum and minimum sums in the subarrays arr[0…i] and arr[i+1 … n-1] for every index i in the array.
leftMax[] : An element leftMax[i] of this array stores the maximum value in subarray arr[0..i] leftMin[] : An element leftMin[i] of this array stores the minimum value in subarray arr[0..i] rightMax[] : An element rightMax[i] of this array stores the maximum value in subarray arr[i+1..n-1] rightMin[] : An element rightMin[i] of this array stores the minimum value in subarray arr[i+1..n-1]
We can build above four arrays in O(n) time by using Kadane Algorithm.
- Kadane’s algorithm can be modified to find minimum absolute sum of a subarray as well. The idea is to change the sign of each element in the array and run Kadane Algorithm to find maximum sum subarray that lies in arr[0…i] and arr[i+1 … n-1]. Now invert the sign of maximum subarray sum found. That will be our minimum subarray sum. This idea is taken from here.
Now from above four arrays, we can easily find maximum absolute difference between the sum of two contiguous sub-arrays. For each index i, take maximum of
- abs(max sum subarray that lies in arr[0…i] – min sum subarray that lies in arr[i+1…n-1])
- abs(min sum subarray that lies in arr[0…i] – max sum subarray that lies in arr[i+1…n-1])
Below is the implementation of above idea.
C++
// C++ program to find two non-overlapping contiguous
// sub-arrays such that the absolute difference
// between the sum of two sub-array is maximum.
#include <bits/stdc++.h>
using
namespace
std;
// Find maximum subarray sum for subarray [0..i]
// using standard Kadane's algorithm. This version of
// Kadane's Algorithm will work if all numbers are
// negative.
int
maxLeftSubArraySum(
int
a[],
int
size,
int
sum[])
{
int
max_so_far = a[0];
int
curr_max = a[0];
sum[0] = max_so_far;
for
(
int
i = 1; i < size; i++)
{
curr_max = max(a[i], curr_max + a[i]);
max_so_far = max(max_so_far, curr_max);
sum[i] = max_so_far;
}
return
max_so_far;
}
// Find maximum subarray sum for subarray [i..n]
// using Kadane's algorithm. This version of Kadane's
// Algorithm will work if all numbers are negative
int
maxRightSubArraySum(
int
a[],
int
n,
int
sum[])
{
int
max_so_far = a[n];
int
curr_max = a[n];
sum[n] = max_so_far;
for
(
int
i = n-1; i >= 0; i--)
{
curr_max = max(a[i], curr_max + a[i]);
max_so_far = max(max_so_far, curr_max);
sum[i] = max_so_far;
}
return
max_so_far;
}
// The function finds two non-overlapping contiguous
// sub-arrays such that the absolute difference
// between the sum of two sub-array is maximum.
int
findMaxAbsDiff(
int
arr[],
int
n)
{
// create and build an array that stores
// maximum sums of subarrays that lie in
// arr[0...i]
int
leftMax[n];
maxLeftSubArraySum(arr, n, leftMax);
// create and build an array that stores
// maximum sums of subarrays that lie in
// arr[i+1...n-1]
int
rightMax[n];
maxRightSubArraySum(arr, n-1, rightMax);
// Invert array (change sign) to find minumum
// sum subarrays.
int
invertArr[n];
for
(
int
i = 0; i < n; i++)
invertArr[i] = -arr[i];
// create and build an array that stores
// minimum sums of subarrays that lie in
// arr[0...i]
int
leftMin[n];
maxLeftSubArraySum(invertArr, n, leftMin);
for
(
int
i = 0; i < n; i++)
leftMin[i] = -leftMin[i];
// create and build an array that stores
// minimum sums of subarrays that lie in
// arr[i+1...n-1]
int
rightMin[n];
maxRightSubArraySum(invertArr, n - 1, rightMin);
for
(
int
i = 0; i < n; i++)
rightMin[i] = -rightMin[i];
int
result = INT_MIN;
for
(
int
i = 0; i < n - 1; i++)
{
/* For each index i, take maximum of
1. abs(max sum subarray that lies in arr[0...i] -
min sum subarray that lies in arr[i+1...n-1])
2. abs(min sum subarray that lies in arr[0...i] -
max sum subarray that lies in arr[i+1...n-1]) */
int
absValue = max(
abs
(leftMax[i] - rightMin[i + 1]),
abs
(leftMin[i] - rightMax[i + 1]));
if
(absValue > result)
result = absValue;
}
return
result;
}
// Driver program
int
main()
{
int
a[] = {-2, -3, 4, -1, -2, 1, 5, -3};
int
n =
sizeof
(a) /
sizeof
(a[0]);
cout << findMaxAbsDiff(a, n);
return
0;
}
Java
// Java program to find two non-overlapping
// contiguous sub-arrays such that the
// absolute difference
import
java.util.*;
class
GFG {
// Find maximum subarray sum for subarray
// [0..i] using standard Kadane's algorithm.
// This version of Kadane's Algorithm will
// work if all numbers are negative.
static
int
maxLeftSubArraySum(
int
a[],
int
size,
int
sum[])
{
int
max_so_far = a[
0
];
int
curr_max = a[
0
];
sum[
0
] = max_so_far;
for
(
int
i =
1
; i < size; i++) {
curr_max = Math.max(a[i], curr_max + a[i]);
max_so_far = Math.max(max_so_far, curr_max);
sum[i] = max_so_far;
}
return
max_so_far;
}
// Find maximum subarray sum for subarray [i..n]
// using Kadane's algorithm. This version of Kadane's
// Algorithm will work if all numbers are negative
static
int
maxRightSubArraySum(
int
a[],
int
n,
int
sum[])
{
int
max_so_far = a[n];
int
curr_max = a[n];
sum[n] = max_so_far;
for
(
int
i = n -
1
; i >=
0
; i--) {
curr_max = Math.max(a[i], curr_max + a[i]);
max_so_far = Math.max(max_so_far, curr_max);
sum[i] = max_so_far;
}
return
max_so_far;
}
// The function finds two non-overlapping contiguous
// sub-arrays such that the absolute difference
// between the sum of two sub-array is maximum.
static
int
findMaxAbsDiff(
int
arr[],
int
n)
{
// create and build an array that stores
// maximum sums of subarrays that lie in
// arr[0...i]
int
leftMax[] =
new
int
[n];
maxLeftSubArraySum(arr, n, leftMax);
// create and build an array that stores
// maximum sums of subarrays that lie in
// arr[i+1...n-1]
int
rightMax[] =
new
int
[n];
maxRightSubArraySum(arr, n -
1
, rightMax);
// Invert array (change sign) to find minumum
// sum subarrays.
int
invertArr[] =
new
int
[n];
for
(
int
i =
0
; i < n; i++)
invertArr[i] = -arr[i];
// create and build an array that stores
// minimum sums of subarrays that lie in
// arr[0...i]
int
leftMin[] =
new
int
[n];
maxLeftSubArraySum(invertArr, n, leftMin);
for
(
int
i =
0
; i < n; i++)
leftMin[i] = -leftMin[i];
// create and build an array that stores
// minimum sums of subarrays that lie in
// arr[i+1...n-1]
int
rightMin[] =
new
int
[n];
maxRightSubArraySum(invertArr, n -
1
, rightMin);
for
(
int
i =
0
; i < n; i++)
rightMin[i] = -rightMin[i];
int
result = -
2147483648
;
for
(
int
i =
0
; i < n -
1
; i++) {
/* For each index i, take maximum of
1. abs(max sum subarray that lies in arr[0...i] -
min sum subarray that lies in arr[i+1...n-1])
2. abs(min sum subarray that lies in arr[0...i] -
max sum subarray that lies in arr[i+1...n-1]) */
int
absValue = Math.max(Math.abs(leftMax[i] - rightMin[i +
1
]),
Math.abs(leftMin[i] - rightMax[i +
1
]));
if
(absValue > result)
result = absValue;
}
return
result;
}
// driver code
public
static
void
main(String[] args)
{
int
a[] = { -
2
, -
3
,
4
, -
1
, -
2
,
1
,
5
, -
3
};
int
n = a.length;
System.out.print(findMaxAbsDiff(a, n));
}
}
// This code is contributed by Anant Agarwal.
Python3
# Python3 program to find two non-
# overlapping contiguous sub-arrays
# such that the absolute difference
# between the sum of two sub-array is maximum.
# Find maximum subarray sum for
# subarray [0..i] using standard
# Kadane's algorithm. This version
# of Kadane's Algorithm will work if
# all numbers are negative.
def
maxLeftSubArraySum(a, size,
sum
):
max_so_far
=
a[
0
]
curr_max
=
a[
0
]
sum
[
0
]
=
max_so_far
for
i
in
range
(
1
, size):
curr_max
=
max
(a[i], curr_max
+
a[i])
max_so_far
=
max
(max_so_far, curr_max)
sum
[i]
=
max_so_far
return
max_so_far
# Find maximum subarray sum for
# subarray [i..n] using Kadane's
# algorithm. This version of Kadane's
# Algorithm will work if all numbers are negative
def
maxRightSubArraySum(a, n,
sum
):
max_so_far
=
a[n]
curr_max
=
a[n]
sum
[n]
=
max_so_far
for
i
in
range
(n
-
1
,
-
1
,
-
1
):
curr_max
=
max
(a[i], curr_max
+
a[i])
max_so_far
=
max
(max_so_far, curr_max)
sum
[i]
=
max_so_far
return
max_so_far
# The function finds two non-overlapping
# contiguous sub-arrays such that the
# absolute difference between the sum
# of two sub-array is maximum.
def
findMaxAbsDiff(arr, n):
# create and build an array that
# stores maximum sums of subarrays
# that lie in arr[0...i]
leftMax
=
[
0
for
i
in
range
(n)]
maxLeftSubArraySum(arr, n, leftMax)
# create and build an array that stores
# maximum sums of subarrays that lie in
# arr[i+1...n-1]
rightMax
=
[
0
for
i
in
range
(n)]
maxRightSubArraySum(arr, n
-
1
, rightMax)
# Invert array (change sign) to
# find minumum sum subarrays.
invertArr
=
[
0
for
i
in
range
(n)]
for
i
in
range
(n):
invertArr[i]
=
-
arr[i]
# create and build an array that stores
# minimum sums of subarrays that lie in
# arr[0...i]
leftMin
=
[
0
for
i
in
range
(n)]
maxLeftSubArraySum(invertArr, n, leftMin)
for
i
in
range
(n):
leftMin[i]
=
-
leftMin[i]
# create and build an array that stores
# minimum sums of subarrays that lie in
# arr[i+1...n-1]
rightMin
=
[
0
for
i
in
range
(n)]
maxRightSubArraySum(invertArr, n
-
1
, rightMin)
for
i
in
range
(n):
rightMin[i]
=
-
rightMin[i]
result
=
-
2147483648
for
i
in
range
(n
-
1
):
''' For each index i, take maximum of
1. abs(max sum subarray that lies in arr[0...i] -
min sum subarray that lies in arr[i+1...n-1])
2. abs(min sum subarray that lies in arr[0...i] -
max sum subarray that lies in arr[i+1...n-1]) '''
absValue
=
max
(
abs
(leftMax[i]
-
rightMin[i
+
1
]),
abs
(leftMin[i]
-
rightMax[i
+
1
]))
if
(absValue > result):
result
=
absValue
return
result
# Driver Code
a
=
[
-
2
,
-
3
,
4
,
-
1
,
-
2
,
1
,
5
,
-
3
]
n
=
len
(a)
print
(findMaxAbsDiff(a, n))
# This code is contributed by Anant Agarwal.
C#
// C# program to find two non-overlapping
// contiguous sub-arrays such that the
// absolute difference
using
System;
class
GFG {
// Find maximum subarray sum for subarray
// [0..i] using standard Kadane's algorithm.
// This version of Kadane's Algorithm will
// work if all numbers are negative.
static
int
maxLeftSubArraySum(
int
[]a,
int
size,
int
[]sum)
{
int
max_so_far = a[0];
int
curr_max = a[0];
sum[0] = max_so_far;
for
(
int
i = 1; i < size; i++)
{
curr_max = Math.Max(a[i], curr_max + a[i]);
max_so_far = Math.Max(max_so_far, curr_max);
sum[i] = max_so_far;
}
return
max_so_far;
}
// Find maximum subarray sum for subarray
// [i..n] using Kadane's algorithm.
// This version of Kadane's Algorithm will
// work if all numbers are negative
static
int
maxRightSubArraySum(
int
[]a,
int
n,
int
[]sum)
{
int
max_so_far = a[n];
int
curr_max = a[n];
sum[n] = max_so_far;
for
(
int
i = n-1; i >= 0; i--)
{
curr_max = Math.Max(a[i], curr_max + a[i]);
max_so_far = Math.Max(max_so_far, curr_max);
sum[i] = max_so_far;
}
return
max_so_far;
}
// The function finds two non-overlapping
// contiguous sub-arrays such that the
// absolute difference between the sum
// of two sub-array is maximum.
static
int
findMaxAbsDiff(
int
[]arr,
int
n)
{
// create and build an array that stores
// maximum sums of subarrays that lie in
// arr[0...i]
int
[]leftMax=
new
int
[n];
maxLeftSubArraySum(arr, n, leftMax);
// create and build an array that stores
// maximum sums of subarrays that lie in
// arr[i+1...n-1]
int
[]rightMax=
new
int
[n];
maxRightSubArraySum(arr, n-1, rightMax);
// Invert array (change sign) to find minumum
// sum subarrays.
int
[]invertArr=
new
int
[n];
for
(
int
i = 0; i < n; i++)
invertArr[i] = -arr[i];
// create and build an array that stores
// minimum sums of subarrays that lie in
// arr[0...i]
int
[]leftMin=
new
int
[n];
maxLeftSubArraySum(invertArr, n, leftMin);
for
(
int
i = 0; i < n; i++)
leftMin[i] = -leftMin[i];
// create and build an array that stores
// minimum sums of subarrays that lie in
// arr[i+1...n-1]
int
[]rightMin=
new
int
[n];
maxRightSubArraySum(invertArr, n - 1, rightMin);
for
(
int
i = 0; i < n; i++)
rightMin[i] = -rightMin[i];
int
result = -2147483648;
for
(
int
i = 0; i < n - 1; i++)
{
/* For each index i, take maximum of
1. abs(max sum subarray that lies in arr[0...i] -
min sum subarray that lies in arr[i+1...n-1])
2. abs(min sum subarray that lies in arr[0...i] -
max sum subarray that lies in arr[i+1...n-1]) */
int
absValue = Math.Max(Math.Abs(leftMax[i] - rightMin[i + 1]),
Math.Abs(leftMin[i] - rightMax[i + 1]));
if
(absValue > result)
result = absValue;
}
return
result;
}
//driver code
public
static
void
Main()
{
int
[]a= {-2, -3, 4, -1, -2, 1, 5, -3};
int
n = a.Length;
Console.Write(findMaxAbsDiff(a, n));
}
}
//This code is contributed by Anant Agarwal.
PHP
<?php
// PHP program to find two non-overlapping
// contiguous sub-arrays such that the
// absolute difference between the sum of
// two sub-array is maximum.
// Find maximum subarray sum for subarray
// [0..i] using standard Kadane's algorithm.
// This version of Kadane's Algorithm will
// work if all numbers are negative
function
maxLeftSubArraySum(&
$a
,
$size
, &
$sum
)
{
$max_so_far
=
$a
[0];
$curr_max
=
$a
[0];
$sum
[0] =
$max_so_far
;
for
(
$i
= 1;
$i
<
$size
;
$i
++)
{
$curr_max
= max(
$a
[
$i
],
$curr_max
+
$a
[
$i
]);
$max_so_far
= max(
$max_so_far
,
$curr_max
);
$sum
[
$i
] =
$max_so_far
;
}
return
$max_so_far
;
}
// Find maximum subarray sum for subarray
// [i..n] using Kadane's algorithm. This
// version of Kadane's Algorithm will work
// if all numbers are negative
function
maxRightSubArraySum(&
$a
,
$n
, &
$sum
)
{
$max_so_far
=
$a
[
$n
];
$curr_max
=
$a
[
$n
];
$sum
[
$n
] =
$max_so_far
;
for
(
$i
=
$n
- 1;
$i
>= 0;
$i
--)
{
$curr_max
= max(
$a
[
$i
],
$curr_max
+
$a
[
$i
]);
$max_so_far
= max(
$max_so_far
,
$curr_max
);
$sum
[
$i
] =
$max_so_far
;
}
return
$max_so_far
;
}
// The function finds two non-overlapping
// contiguous sub-arrays such that the
// absolute difference between the sum of
// two sub-array is maximum.
function
findMaxAbsDiff(&
$arr
,
$n
)
{
// create and build an array that stores
// maximum sums of subarrays that lie in
// arr[0...i]
$leftMax
=
array_fill
(0,
$n
, NULL);
maxLeftSubArraySum(
$arr
,
$n
,
$leftMax
);
// create and build an array that stores
// maximum sums of subarrays that lie in
// arr[i+1...n-1]
$rightMax
=
array_fill
(0,
$n
, NULL);
maxRightSubArraySum(
$arr
,
$n
- 1,
$rightMax
);
// Invert array (change sign) to
// find minumum sum subarrays
$invertArr
=
array_fill
(0,
$n
, NULL);
for
(
$i
= 0;
$i
<
$n
;
$i
++)
$invertArr
[
$i
] = -
$arr
[
$i
];
// create and build an array that stores
// minimum sums of subarrays that lie in
// arr[0...i]
$leftMin
=
array_fill
(0,
$n
, NULL);
maxLeftSubArraySum(
$invertArr
,
$n
,
$leftMin
);
for
(
$i
= 0;
$i
<
$n
;
$i
++)
$leftMin
[
$i
] = -
$leftMin
[
$i
];
// create and build an array that stores
// minimum sums of subarrays that lie in
// arr[i+1...n-1]
$rightMin
=
array_fill
(0,
$n
, NULL);
maxRightSubArraySum(
$invertArr
,
$n
- 1,
$rightMin
);
for
(
$i
= 0;
$i
<
$n
;
$i
++)
$rightMin
[
$i
] = -
$rightMin
[
$i
];
$result
= PHP_INT_MIN;
for
(
$i
= 0;
$i
<
$n
- 1;
$i
++)
{
/* For each index i, take maximum of
1. abs(max sum subarray that lies
in arr[0...i] - min sum subarray
that lies in arr[i+1...n-1])
2. abs(min sum subarray that lies
in arr[0...i] - max sum subarray
that lies in arr[i+1...n-1]) */
$absValue
= max(
abs
(
$leftMax
[
$i
] -
$rightMin
[
$i
+ 1]),
abs
(
$leftMin
[
$i
] -
$rightMax
[
$i
+ 1]));
if
(
$absValue
>
$result
)
$result
=
$absValue
;
}
return
$result
;
}
// Driver Code
$a
=
array
(-2, -3, 4, -1, -2, 1, 5, -3);
$n
= sizeof(
$a
);
echo
findMaxAbsDiff(
$a
,
$n
);
// This code is contributed
// by ChitraNayal
?>
Output :12
Time Complexity is O(n) where n is the number of elements in input array. Auxiliary Space required is O(n).
This article is contributed by Aditya Goel. If you like GeeksforGeeks and would like to contribute, you can also write an article and mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above
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.
In order to calculate maximum sum subarray that lies in arr[0…i], we run Kadane Algorithm from 0 to n-1 and to find maximum sum subarray that lies in arr[i+1 … n-1], we run Kadane Algorithm from n-1 to 0.