Maximum subarray sum modulo m
Given an array of n elements and an integer m. The task is to find the maximum value of the sum of its subarray modulo m i.e find the sum of each subarray mod m and print the maximum value of this modulo operation.
Examples:
Input : arr[] = { 3, 3, 9, 9, 5 }
m = 7
Output : 6
All sub-arrays and their value:
{ 9 } => 9%7 = 2
{ 3 } => 3%7 = 3
{ 5 } => 5%7 = 5
{ 9, 5 } => 14%7 = 2
{ 9, 9 } => 18%7 = 4
{ 3, 9 } => 12%7 = 5
{ 3, 3 } => 6%7 = 6
{ 3, 9, 9 } => 21%7 = 0
{ 3, 3, 9 } => 15%7 = 1
{ 9, 9, 5 } => 23%7 = 2
{ 3, 3, 9, 9 } => 24%7 = 3
{ 3, 9, 9, 5 } => 26%7 = 5
{ 3, 3, 9, 9, 5 } => 29%7 = 1
Input : arr[] = {10, 7, 18}
m = 13
Output : 12
The subarray {7, 18} has maximum sub-array
sum modulo 13.
Method 1 (Brute Force):
Use brute force to find all the subarrays of the given array and find sum of each subarray mod m and keep track of maximum.
Method 2 (efficient approach):
The idea is to compute prefix sum of array. We find maximum sum ending with every index and finally return the overall maximum. To find maximum sum ending at an index, we need to find the starting point of maximum sum ending with i.
Below steps explain how to find the starting point.
Let prefix sum for index i be prefixi, i.e.,
prefixi = (arr[0] + arr[1] + .... arr[i] ) % m
Let maximum sum ending with i be, maxSumi.
Let this sum begins with index j.
maxSumi = (prefixi - prefixj + m) % m
From above expression it is clear that the
value of maxSumi becomes maximum when
prefixj is greater than prefixi
and closest to prefixi
We mainly have two operations in above algorithm.
- Store all prefixes.
- For current prefix, prefixi, find the smallest value greater than or equal to prefixi + 1.
For above operations, self-balancing-binary-search trees like AVL Tree, Red-Black Tree, etc are best suited. In below implementation we use set in STL which implements a self-balancing-binary-search-tree.
Below is the implementation of this approach:
C++
#include<bits/stdc++.h>
using namespace std;
int maxSubarray( int arr[], int n, int m)
{
int prefix = 0, maxim = 0;
set< int > S;
S.insert(0);
for ( int i = 0; i < n; i++)
{
prefix = (prefix + arr[i])%m;
maxim = max(maxim, prefix);
auto it = S.lower_bound(prefix+1);
if (it != S.end())
maxim = max(maxim, prefix - (*it) + m );
S.insert(prefix);
}
return maxim;
}
int main()
{
int arr[] = { 3, 3, 9, 9, 5 };
int n = sizeof (arr)/ sizeof (arr[0]);
int m = 7;
cout << maxSubarray(arr, n, m) << endl;
return 0;
}
|
Java
import java.util.*;
class GFG
{
static int maxSubarray( int [] arr, int n, int m)
{
int prefix = 0 ;
int maxim = 0 ;
Set<Integer> S = new HashSet<Integer>();
S.add( 0 );
for ( int i = 0 ; i < n; i++)
{
prefix = (prefix + arr[i]) % m;
maxim = Math.max(maxim, prefix);
int it = 0 ;
for ( int j : S)
{
if (j >= prefix + 1 )
it = j;
}
if (it != 0 )
{
maxim = Math.max(maxim, prefix - it + m);
}
S.add(prefix);
}
return maxim;
}
public static void main(String[] args)
{
int [] arr = new int [] { 3 , 3 , 9 , 9 , 5 };
int n = 5 ;
int m = 7 ;
System.out.print(maxSubarray(arr, n, m));
}
}
|
Python3
def maxSubarray(arr, n, m):
prefix = 0
maxim = 0
S = set ()
S.add( 0 )
for i in range (n):
prefix = (prefix + arr[i]) % m
maxim = max (maxim, prefix)
it = 0
for i in S:
if i > = prefix + 1 :
it = i
if (it ! = 0 ) :
maxim = max (maxim, prefix - it + m )
S.add(prefix)
return maxim
arr = [ 3 , 3 , 9 , 9 , 5 ]
n = 5
m = 7
print (maxSubarray(arr, n, m))
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
class GFG
{
static int maxSubarray( int [] arr, int n, int m)
{
int prefix = 0;
int maxim = 0;
HashSet< int > S = new HashSet< int >();
S.Add(0);
for ( int i = 0; i < n; i++)
{
prefix = (prefix + arr[i]) % m;
maxim = Math.Max(maxim, prefix);
int it = 0;
foreach ( int j in S)
{
if (j >= prefix + 1)
it = j;
}
if (it != 0)
{
maxim = Math.Max(maxim, prefix - it + m);
}
S.Add(prefix);
}
return maxim;
}
public static void Main( string [] args)
{
int [] arr = new int [] { 3, 3, 9, 9, 5 };
int n = 5;
int m = 7;
Console.Write(maxSubarray(arr, n, m));
}
}
|
Javascript
<script>
function maxSubarray(arr,n,m)
{
let prefix = 0;
let maxim = 0;
let S = new Set();
S.add(0);
for (let i = 0; i < n; i++)
{
prefix = (prefix + arr[i]) % m;
maxim = Math.max(maxim, prefix);
let it = 0;
for (let j of S.values())
{
if (j >= prefix + 1)
it = j;
}
if (it != 0)
{
maxim = Math.max(maxim, prefix - it + m);
}
S.add(prefix);
}
return maxim;
}
let arr=[3, 3, 9, 9, 5];
let n = 5;
let m = 7;
document.write(maxSubarray(arr, n, m));
</script>
|
Time Complexity: O(n*log(n))
Auxiliary Space: O(n)
Reference:
http://stackoverflow.com/questions/31113993/maximum-subarray-sum-modulo-m
Last Updated :
30 Dec, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...