Find a subarray whose sum is divisible by size of the array
Given an array arr[] of length N. The task is to check if there exists any subarray whose sum is a multiple of N. If there exists such subarray, then print the starting and ending index of that subarray else print -1. If there are multiple such subarrays, print any of them.
Examples:
Input: arr[] = {7, 5, 3, 7}
Output: 0 1
Sub-array from index 0 to 1 is [7, 5]
sum of this subarray is 12 which is a multiple of 4
Input: arr[] = {3, 7, 14}
Output: 0 0
Naive Approach: The naive approach is to generate all the sub-arrays and calculate their sum. If the sum for any subarray is a multiple of N, then return the starting as well as ending index.
Time Complexity: O(N3)
Better Approach: A better approach is to maintain a prefix sum array that stores the sum of all previous elements. To calculate the sum of a subarray between index i and j, we can use the formula:
subarray sum[i:j] = presum[j]-presum[i-1]
Now check for every sub-array whether its sum is a multiple of N or not.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
void CheckSubarray( int arr[], int N)
{
int presum[N + 1] = { 0 };
for ( int i = 1; i <= N; i += 1) {
presum[i] = presum[i - 1] + arr[i - 1];
}
for ( int i = 1; i <= N; i += 1) {
for ( int j = i; j <= N; j += 1) {
if ((presum[j] - presum[i - 1]) % N == 0) {
cout << i - 1 << " " << j - 1;
return ;
}
}
}
cout << -1;
}
int main()
{
int arr[] = { 7, 5, 3, 7 };
int N = sizeof (arr) / sizeof (arr[0]);
CheckSubarray(arr, N);
return 0;
}
|
Java
import java.io.*;
class GFG
{
static void CheckSubarray( int arr[], int N)
{
int presum[] = new int [N + 1 ];
for ( int i = 1 ; i <= N; i += 1 )
{
presum[i] = presum[i - 1 ] + arr[i - 1 ];
}
for ( int i = 1 ; i <= N; i += 1 )
{
for ( int j = i; j <= N; j += 1 )
{
if ((presum[j] - presum[i - 1 ]) % N == 0 )
{
System.out.print((i - 1 ) + " " + (j - 1 ));
return ;
}
}
}
System.out.print(- 1 );
}
public static void main (String[] args)
{
int []arr = { 7 , 5 , 3 , 7 };
int N = arr.length;
CheckSubarray(arr, N);
}
}
|
Python3
def CheckSubarray(arr, N):
presum = [ 0 for i in range (N + 1 )]
for i in range ( 1 , N + 1 ):
presum[i] = presum[i - 1 ] + arr[i - 1 ]
for i in range ( 1 , N + 1 ):
for j in range (i, N + 1 ):
if ((presum[j] - presum[i - 1 ]) % N = = 0 ):
print (i - 1 ,j - 1 )
return
print ( "-1" )
arr = [ 7 , 5 , 3 , 7 ]
N = len (arr)
CheckSubarray(arr, N)
|
C#
using System;
class GFG
{
static void CheckSubarray( int []arr, int N)
{
int []presum = new int [N + 1];
for ( int i = 1; i <= N; i += 1)
{
presum[i] = presum[i - 1] + arr[i - 1];
}
for ( int i = 1; i <= N; i += 1)
{
for ( int j = i; j <= N; j += 1)
{
if ((presum[j] - presum[i - 1]) % N == 0)
{
Console.Write((i - 1) + " " + (j - 1));
return ;
}
}
}
Console.Write(-1);
}
public static void Main ()
{
int []arr = { 7, 5, 3, 7 };
int N = arr.Length;
CheckSubarray(arr, N);
}
}
|
Javascript
<script>
function CheckSubarray(arr, N)
{
let presum = new Array(N + 1).fill(0);
for (let i = 1; i <= N; i += 1) {
presum[i] = presum[i - 1] + arr[i - 1];
}
for (let i = 1; i <= N; i += 1) {
for (let j = i; j <= N; j += 1) {
if ((presum[j] - presum[i - 1]) % N == 0) {
document.write((i - 1) + " " + (j - 1));
return ;
}
}
}
document.write(-1);
}
let arr = [ 7, 5, 3, 7 ];
let N = arr.length;
CheckSubarray(arr, N);
</script>
|
Time Complexity: O(N2)
Auxiliary Space: O(N)
Efficient Approach: The idea is to use the Pigeon-Hole Principle. Let’s suppose the array elements are a1, a2…aN.
For a sequence of numbers as follows:
a1, a1 + a2, a1 + a2 + a3, …, a1 + a2 +a3 + … +aN
In the above sequence, there are N terms. There are two possible cases:
- If one of the above prefix sums is a multiple of N then print the ith subarray indices.
- If None of the above sequence elements lies in the 0 modulo class of N, then there are (N – 1) modulo classes left. By the pigeon-hole principle, there are N pigeons (elements of the prefix sum sequence) and (N – 1) holes (modulo classes), we can say that at least two elements would lie in the same modulo class. The difference between these two elements would give a sub-array whose sum will be a multiple of N.
It could be seen that it is always possible to get such a sub-array.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
void CheckSubarray( int arr[], int N)
{
int presum[N + 1] = { 0 };
for ( int i = 1; i <= N; i += 1) {
presum[i] = presum[i - 1] + arr[i - 1];
}
vector< int > moduloclass[N];
for ( int i = 1; i <= N; i += 1) {
moduloclass[presum[i] % N].push_back(i - 1);
}
if (moduloclass[0].size() > 0) {
cout << 0 << " " << moduloclass[0][0];
return ;
}
for ( int i = 1; i < N; i += 1) {
if (moduloclass[i].size() >= 2) {
cout << moduloclass[i][0] + 1 << " " << moduloclass[i][1];
return ;
}
}
}
int main()
{
int arr[] = { 7, 3, 5, 2 };
int N = sizeof (arr) / sizeof (arr[0]);
CheckSubarray(arr, N);
return 0;
}
|
Java
import java.util.*;
class GFG
{
static void CheckSubarray( int arr[], int N)
{
int [] presum = new int [N + 1 ];
for ( int i = 1 ; i <= N; i += 1 )
{
presum[i] = presum[i - 1 ] + arr[i - 1 ];
}
Vector<Integer>[] moduloclass = new Vector[N];
for ( int i = 0 ; i < N; i += 1 )
{
moduloclass[i] = new Vector<>();
}
for ( int i = 1 ; i <= N; i += 1 )
{
moduloclass[presum[i] % N].add(i - 1 );
}
if (moduloclass[ 0 ].size() > 0 )
{
System.out.print( 0 + " " +
moduloclass[ 0 ].get( 0 ));
return ;
}
for ( int i = 1 ; i < N; i += 1 )
{
if (moduloclass[i].size() >= 2 )
{
System.out.print(moduloclass[i].get( 0 ) + 1 +
" " + moduloclass[i].get( 1 ));
return ;
}
}
}
public static void main(String args[])
{
int arr[] = { 7 , 3 , 5 , 2 };
int N = arr.length;
CheckSubarray(arr, N);
}
}
|
Python3
def CheckSubarray(arr, N):
presum = [ 0 for i in range (N + 1 )]
for i in range ( 1 ,N + 1 ):
presum[i] = presum[i - 1 ] + arr[i - 1 ]
moduloclass = [[]] * N
for i in range ( 1 ,N + 1 , 1 ):
moduloclass[presum[i] % N].append(i - 1 )
if ( len (moduloclass[ 0 ]) > 0 ):
print ( 0 + 1 ,moduloclass[ 0 ][ 0 ] + 2 )
return
for i in range ( 1 ,N):
if ( len (moduloclass[i]) > = 2 ):
print (moduloclass[i][ 0 ] + 1 ,moduloclass[i][ 1 ])
return
if __name__ = = '__main__' :
arr = [ 7 , 3 , 5 , 2 ]
N = len (arr)
CheckSubarray(arr, N)
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static void CheckSubarray( int []arr, int N)
{
int [] presum = new int [N + 1];
for ( int i = 1; i <= N; i += 1)
{
presum[i] = presum[i - 1] + arr[i - 1];
}
List< int >[] moduloclass = new List< int >[N];
for ( int i = 0; i < N; i += 1)
{
moduloclass[i] = new List< int >();
}
for ( int i = 1; i <= N; i += 1)
{
moduloclass[presum[i] % N].Add(i - 1);
}
if (moduloclass[0].Count > 0)
{
Console.Write(0 + " " +
moduloclass[0][0]);
return ;
}
for ( int i = 1; i < N; i += 1)
{
if (moduloclass[i].Count >= 2)
{
Console.Write(moduloclass[i][0] + 1 +
" " + moduloclass[i][1]);
return ;
}
}
}
public static void Main(String []args)
{
int []arr = {7, 3, 5, 2};
int N = arr.Length;
CheckSubarray(arr, N);
}
}
|
Javascript
<script>
function CheckSubarray(arr, N)
{
let presum = new Array(N + 1);
for (let i = 0; i < (N + 1); i++)
presum[i] = 0;
for (let i = 1; i <= N; i += 1)
{
presum[i] = presum[i - 1] + arr[i - 1];
}
let moduloclass = new Array(N);
for (let i = 0; i < N; i += 1)
{
moduloclass[i] = [];
}
for (let i = 1; i <= N; i += 1)
{
moduloclass[presum[i] % N].push(i - 1);
}
if (moduloclass[0].length > 0)
{
document.write(0 + " " +
moduloclass[0][0]);
return ;
}
for (let i = 1; i < N; i += 1)
{
if (moduloclass[i].length >= 2)
{
document.write(moduloclass[i][0] + 1 +
" " + moduloclass[i][1]);
return ;
}
}
}
let arr = [ 7, 3, 5, 2 ];
let N = arr.length;
CheckSubarray(arr, N);
</script>
|
Time Complexity: O(n)
Auxiliary Space: O(n)
Last Updated :
31 May, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...