Given an array arr[] consisting of positive numbers, the task is to find the maximum range [L, R] whose sum is divisible by M. If there is no range present return -1. Examples:
Input: arr[] = {3, 7, 5, 2, 5, 10}, M = 3 Output: 1 3 Explanation: Sum of numbers from 1 to 3 is 3+7+5 which is 15. Input : A[] = {4, 8, 12, 16, 20} M = 11 Output : -1
Naive Approach: A naive approach is that we can iterate through all possible L and R in the array and check if the sum is divisible. If it is, then store the length of the array. Efficient Approach: The idea here is to use a prefix sum array.
- Initially, the prefix sum of the values is calculated.
- Once the prefix sum is calculated, every value is replaced by the value modulo M.
- The indices where the final value is equal is the range where the sum is perfectly divisible by M.
- The maximum range of the same values is found.
Below is the implementation of the above approach,
// C++ implementation of the above approach. #include <bits/stdc++.h> using namespace std;
// Function to find the maximum range // whose sum is divisible by M. pair< int , int > maxrange( int n,
int a[], int m)
{ int pre[n + 5];
map< int , set< int > > mpp;
int value, l, r, lans = -1,
rans = -1, ans = 0;
// Calculate the prefix sum
pre[0] = a[0];
for ( int i = 1; i < n; i++) {
pre[i] = a[i] + pre[i - 1];
}
// Replacing the values with modulo M
// and inserting the indices into the map
for ( int i = 0; i < n; i++) {
pre[i] = pre[i] % m;
mpp[pre[i]].insert(i);
}
// Calculate the range [L, R]
for ( auto it = mpp.begin(); it != mpp.end(); it++) {
if (it->first == 0) {
value = *((it->second).rbegin()) + 1;
l = 1;
r = value;
}
else {
value = *((it->second).rbegin())
- *((it->second.begin()));
l = *((it->second.begin())) + 2;
r = *((it->second).rbegin()) + 1;
}
if (value > ans && l <= r) {
ans = value;
lans = l;
rans = r;
}
}
return make_pair(lans, rans);
} // Driver code int main()
{ int A[] = { 3, 7, 5, 2, 5, 10 };
int N = sizeof (A) / sizeof (A[0]);
int M = 3;
pair< int , int > value = maxrange(N, A, M);
if (value.first == -1) {
cout << -1 << "\n" ;
}
else {
cout << value.first << " "
<< value.second << "\n" ;
}
return 0;
} |
import java.util.*;
class GFG {
// Function to find the maximum range
// whose sum is divisible by M.
static Pair<Integer, Integer> maxRange( int n, int [] a, int m) {
int [] pre = new int [n + 5 ];
TreeMap<Integer, TreeSet<Integer>> mpp = new TreeMap<>();
int value, l, r, lans = - 1 , rans = - 1 , ans = 0 ;
// Calculate the prefix sum
pre[ 0 ] = a[ 0 ];
for ( int i = 1 ; i < n; i++) {
pre[i] = a[i] + pre[i - 1 ];
}
// Replacing the values with modulo M
// and inserting the indices into the map
for ( int i = 0 ; i < n; i++) {
pre[i] = pre[i] % m;
if (!mpp.containsKey(pre[i])) {
mpp.put(pre[i], new TreeSet<>());
}
mpp.get(pre[i]).add(i);
}
// Calculate the range [L, R]
for (Map.Entry<Integer, TreeSet<Integer>> entry : mpp.entrySet()) {
int key = entry.getKey();
TreeSet<Integer> indices = entry.getValue();
if (key == 0 ) {
value = indices.last() + 1 ;
l = 1 ;
r = value;
} else {
value = indices.last() - indices.first();
l = indices.first() + 2 ;
r = indices.last() + 1 ;
}
if (value > ans && l <= r) {
ans = value;
lans = l;
rans = r;
}
}
return new Pair<>(lans, rans);
}
// Driver code
public static void main(String[] args) {
int [] A = { 3 , 7 , 5 , 2 , 5 , 10 };
int N = A.length;
int M = 3 ;
Pair<Integer, Integer> value = maxRange(N, A, M);
if (value.getKey() == - 1 ) {
System.out.println(- 1 );
} else {
System.out.println(value.getKey() + " " + value.getValue());
}
}
// Pair class to represent a pair of values
static class Pair<T, U> {
T first;
U second;
public Pair(T first, U second) {
this .first = first;
this .second = second;
}
public T getKey() {
return first;
}
public U getValue() {
return second;
}
}
} |
# Function to find the maximum range # whose sum is divisible by M. def maxrange(n, a, m):
pre = [ 0 ] * (n + 5 )
mpp = {}
value, l, r, lans, rans, ans = - 1 , - 1 , - 1 , 0 , 0 , 0
# Calculate the prefix sum
pre[ 0 ] = a[ 0 ]
for i in range ( 1 , n):
pre[i] = a[i] + pre[i - 1 ]
# Replacing the values with modulo M
# and inserting the indices into the map
for i in range (n):
pre[i] = pre[i] % m
if pre[i] not in mpp:
mpp[pre[i]] = set ()
mpp[pre[i]].add(i)
# Calculate the range [L, R]
for key in mpp:
if key = = 0 :
value = max (mpp[key]) + 1
l, r = 1 , value
else :
value = max (mpp[key]) - min (mpp[key])
l, r = min (mpp[key]) + 2 , max (mpp[key]) + 1
if value > ans and l < = r:
ans = value
lans = l
rans = r
return (lans, rans)
# Driver code A = [ 3 , 7 , 5 , 2 , 5 , 10 ]
N = len (A)
M = 3
value = maxrange(N, A, M)
if value[ 0 ] = = - 1 :
print ( - 1 )
else :
print (value[ 0 ], value[ 1 ])
# This code is contributed by shiv1o43g |
using System;
using System.Collections.Generic;
class GFG
{ // Function to find the maximum range
// whose sum is divisible by M.
static ( int , int ) MaxRange( int n, int [] a, int m)
{
int [] pre = new int [n + 5];
SortedDictionary< int , SortedSet< int >> mpp = new SortedDictionary< int , SortedSet< int >>();
int value, l, r, lans = -1, rans = -1, ans = 0;
// Calculate the prefix sum
pre[0] = a[0];
for ( int i = 1; i < n; i++)
{
pre[i] = a[i] + pre[i - 1];
}
// Replacing the values with modulo M
// and inserting the indices into the map
for ( int i = 0; i < n; i++)
{
pre[i] = pre[i] % m;
if (!mpp.ContainsKey(pre[i]))
{
mpp[pre[i]] = new SortedSet< int >();
}
mpp[pre[i]].Add(i);
}
// Calculate the range [L, R]
foreach ( var entry in mpp)
{
int key = entry.Key;
SortedSet< int > indices = entry.Value;
if (key == 0)
{
value = indices.Max + 1;
l = 1;
r = value;
}
else
{
value = indices.Max - indices.Min;
l = indices.Min + 2;
r = indices.Max + 1;
}
if (value > ans && l <= r)
{
ans = value;
lans = l;
rans = r;
}
}
return (lans, rans);
}
// Driver code
public static void Main( string [] args)
{
int [] A = { 3, 7, 5, 2, 5, 10 };
int N = A.Length;
int M = 3;
var value = MaxRange(N, A, M);
if (value.Item1 == -1)
{
Console.WriteLine(-1);
}
else
{
Console.WriteLine($ "{value.Item1} {value.Item2}" );
}
}
} |
// Function to find the maximum range // whose sum is divisible by M. function maxRange(n, a, m) {
let pre = new Array(n + 5).fill(0);
let mpp = {};
let value = -1;
let l = -1;
let r = -1;
let lans = 0;
let rans = 0;
let ans = 0;
// Calculate the prefix sum
pre[0] = a[0];
for (let i = 1; i < n; i++) {
pre[i] = a[i] + pre[i - 1];
}
// Replacing the values with modulo M
// and inserting the indices into the map
for (let i = 0; i < n; i++) {
pre[i] = pre[i] % m;
if (!mpp[pre[i]]) {
mpp[pre[i]] = new Set();
}
mpp[pre[i]].add(i);
}
// Calculate the range [L, R]
for (let key in mpp) {
key = parseInt(key);
if (key === 0) {
value = Math.max(...mpp[key]) + 1;
l = 1;
r = value;
} else {
value = Math.max(...mpp[key]) - Math.min(...mpp[key]);
l = Math.min(...mpp[key]) + 2;
r = Math.max(...mpp[key]) + 1;
}
if (value > ans && l <= r) {
ans = value;
lans = l;
rans = r;
}
}
return [lans, rans];
} // Driver code const A = [3, 7, 5, 2, 5, 10]; const N = A.length; const M = 3; const value = maxRange(N, A, M); if (value[0] === -1) {
console.log(-1);
} else {
console.log(value[0], value[1]);
} |
1 3