Open In App

Maximum absolute difference between sum of two contiguous sub-arrays

Improve
Improve
Like Article
Like
Save
Share
Report

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.

  1. 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.
  2. 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

  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])

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 minimum
    // 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 minimum
        // 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 minimum 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 minimum
    // 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 minimum 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
?>


Javascript




// 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)
{
    var max_so_far = a[0];
    var curr_max = a[0];
    sum[0] = max_so_far;
    var i=0;
    for (i; 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
function maxRightSubArraySum(a, n, sum)
{
    var max_so_far = a[n];
    var curr_max = a[n];
    sum[n] = max_so_far;
    var i=0;
    for (i; 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.
function findMaxAbsDiff(arr, n)
{
 
    // create and build an array that stores
    // maximum sums of subarrays that lie in
    // arr[0...i]
    var leftMax = Array(n).fill(0);
    maxLeftSubArraySum(arr, n, leftMax);
     
    // create and build an array that stores
    // maximum sums of subarrays that lie in
    // arr[i+1...n-1]
    var rightMax = Array(n).fill(0);
    maxRightSubArraySum(arr, n - 1, rightMax);
     
    // Invert array (change sign) to find minimum
    // sum subarrays.
    var invertArr = Array(n).fill(0);
    var i=0;
    for (i; i < n; i++)
    {
        invertArr[i] = -arr[i];
    }
     
    // create and build an array that stores
    // minimum sums of subarrays that lie in
    // arr[0...i]
    var leftMin = Array(n).fill(0);
    maxLeftSubArraySum(invertArr, n, leftMin);
    var i=0;
    for (i; 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]
    var rightMin = Array(n).fill(0);
    maxRightSubArraySum(invertArr, n - 1, rightMin);
    var i=0;
    for (i; i < n; i++)
    {
        rightMin[i] = -rightMin[i];
    }
    var result = -2147483648;
    var i=0;
    for (i; 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])
        var 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
 
    var a = [-2, -3, 4, -1, -2, 1, 5, -3];
    var n = a.length;
    console.log(findMaxAbsDiff(a, n));
     
    // This code is contributed by sourabhdalal0001.


Output

12

Time Complexity is O(n) where n is the number of elements in input array. Auxiliary Space required is O(n). 



Last Updated : 06 Dec, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads