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 4Input: 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++ implementation of above approach #include <bits/stdc++.h> using namespace std;
// Function to find a subarray // whose sum is a multiple of N void CheckSubarray( int arr[], int N)
{ // Prefix sum array to store cumulative sum
int presum[N + 1] = { 0 };
// Single state dynamic programming
// relation for prefix sum array
for ( int i = 1; i <= N; i += 1) {
presum[i] = presum[i - 1] + arr[i - 1];
}
// Generating all sub-arrays
for ( int i = 1; i <= N; i += 1) {
for ( int j = i; j <= N; j += 1) {
// If the sum of the sub-array[i:j]
// is a multiple of N
if ((presum[j] - presum[i - 1]) % N == 0) {
cout << i - 1 << " " << j - 1;
return ;
}
}
}
// If the function reaches here it means
// there are no subarrays with sum
// as a multiple of N
cout << -1;
} // Driver code int main()
{ int arr[] = { 7, 5, 3, 7 };
int N = sizeof (arr) / sizeof (arr[0]);
CheckSubarray(arr, N);
return 0;
} |
// Java implementation of above approach import java.io.*;
class GFG
{ // Function to find a subarray // whose sum is a multiple of N static void CheckSubarray( int arr[], int N)
{ // Prefix sum array to store cumulative sum
int presum[] = new int [N + 1 ];
// Single state dynamic programming
// relation for prefix sum array
for ( int i = 1 ; i <= N; i += 1 )
{
presum[i] = presum[i - 1 ] + arr[i - 1 ];
}
// Generating all sub-arrays
for ( int i = 1 ; i <= N; i += 1 )
{
for ( int j = i; j <= N; j += 1 )
{
// If the sum of the sub-array[i:j]
// is a multiple of N
if ((presum[j] - presum[i - 1 ]) % N == 0 )
{
System.out.print((i - 1 ) + " " + (j - 1 ));
return ;
}
}
}
// If the function reaches here it means
// there are no subarrays with sum
// as a multiple of N
System.out.print(- 1 );
} // Driver code public static void main (String[] args)
{ int []arr = { 7 , 5 , 3 , 7 };
int N = arr.length;
CheckSubarray(arr, N);
} } // This code is contributed by anuj_67.. |
# Python3 implementation of above approach # Function to find a subarray # whose sum is a multiple of N def CheckSubarray(arr, N):
# Prefix sum array to store cumulative sum
presum = [ 0 for i in range (N + 1 )]
# Single state dynamic programming
# relation for prefix sum array
for i in range ( 1 , N + 1 ):
presum[i] = presum[i - 1 ] + arr[i - 1 ]
# Generating all sub-arrays
for i in range ( 1 , N + 1 ):
for j in range (i, N + 1 ):
# If the sum of the sub-array[i:j]
# is a multiple of N
if ((presum[j] - presum[i - 1 ]) % N = = 0 ):
print (i - 1 ,j - 1 )
return
# If the function reaches here it means
# there are no subarrays with sum
# as a multiple of N
print ( "-1" )
# Driver code arr = [ 7 , 5 , 3 , 7 ]
N = len (arr)
CheckSubarray(arr, N) # This code is contributed by mohit kumar 29 |
// C# implementation of above approach using System;
class GFG
{ // Function to find a subarray // whose sum is a multiple of N static void CheckSubarray( int []arr, int N)
{ // Prefix sum array to store cumulative sum
int []presum = new int [N + 1];
// Single state dynamic programming
// relation for prefix sum array
for ( int i = 1; i <= N; i += 1)
{
presum[i] = presum[i - 1] + arr[i - 1];
}
// Generating all sub-arrays
for ( int i = 1; i <= N; i += 1)
{
for ( int j = i; j <= N; j += 1)
{
// If the sum of the sub-array[i:j]
// is a multiple of N
if ((presum[j] - presum[i - 1]) % N == 0)
{
Console.Write((i - 1) + " " + (j - 1));
return ;
}
}
}
// If the function reaches here it means
// there are no subarrays with sum
// as a multiple of N
Console.Write(-1);
} // Driver code public static void Main ()
{ int []arr = { 7, 5, 3, 7 };
int N = arr.Length;
CheckSubarray(arr, N);
} } // This code is contributed by anuj_67.. |
<script> // Javascript implementation of above approach // Function to find a subarray // whose sum is a multiple of N function CheckSubarray(arr, N)
{ // Prefix sum array to store cumulative sum
let presum = new Array(N + 1).fill(0);
// Single state dynamic programming
// relation for prefix sum array
for (let i = 1; i <= N; i += 1) {
presum[i] = presum[i - 1] + arr[i - 1];
}
// Generating all sub-arrays
for (let i = 1; i <= N; i += 1) {
for (let j = i; j <= N; j += 1) {
// If the sum of the sub-array[i:j]
// is a multiple of N
if ((presum[j] - presum[i - 1]) % N == 0) {
document.write((i - 1) + " " + (j - 1));
return ;
}
}
}
// If the function reaches here it means
// there are no subarrays with sum
// as a multiple of N
document.write(-1);
} // Driver code let arr = [ 7, 5, 3, 7 ];
let N = arr.length;
CheckSubarray(arr, N);
</script> |
0 1
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++ implementation of above approach #include <bits/stdc++.h> using namespace std;
// Function to check is there exists a // subarray whose sum is a multiple of N void CheckSubarray( int arr[], int N)
{ // Prefix sum array to store cumulative sum
int presum[N + 1] = { 0 };
// Single state dynamic programming
// relation for prefix sum array
for ( int i = 1; i <= N; i += 1) {
presum[i] = presum[i - 1] + arr[i - 1];
}
// Modulo class vector
vector< int > moduloclass[N];
// Storing the index value in the modulo class vector
for ( int i = 1; i <= N; i += 1) {
moduloclass[presum[i] % N].push_back(i - 1);
}
// If there exists a sub-array with
// starting index equal to zero
if (moduloclass[0].size() > 0) {
cout << 0 << " " << moduloclass[0][0];
return ;
}
for ( int i = 1; i < N; i += 1) {
// In this class, there are more than two presums%N
// Hence difference of any two subarrays would be a
// multiple of N
if (moduloclass[i].size() >= 2) {
// 0 based indexing
cout << moduloclass[i][0] + 1 << " " << moduloclass[i][1];
return ;
}
}
} // Driver code int main()
{ int arr[] = { 7, 3, 5, 2 };
int N = sizeof (arr) / sizeof (arr[0]);
CheckSubarray(arr, N);
return 0;
} |
// Java implementation of above approach import java.util.*;
class GFG
{ // Function to check is there exists a // subarray whose sum is a multiple of N static void CheckSubarray( int arr[], int N)
{ // Prefix sum array to store cumulative sum
int [] presum = new int [N + 1 ];
// Single state dynamic programming
// relation for prefix sum array
for ( int i = 1 ; i <= N; i += 1 )
{
presum[i] = presum[i - 1 ] + arr[i - 1 ];
}
// Modulo class vector
Vector<Integer>[] moduloclass = new Vector[N];
for ( int i = 0 ; i < N; i += 1 )
{
moduloclass[i] = new Vector<>();
}
// Storing the index value
// in the modulo class vector
for ( int i = 1 ; i <= N; i += 1 )
{
moduloclass[presum[i] % N].add(i - 1 );
}
// If there exists a sub-array with
// starting index equal to zero
if (moduloclass[ 0 ].size() > 0 )
{
System.out.print( 0 + " " +
moduloclass[ 0 ].get( 0 ));
return ;
}
for ( int i = 1 ; i < N; i += 1 )
{
// In this class, there are more than
// two presums%N. Hence difference of
// any two subarrays would be a multiple of N
if (moduloclass[i].size() >= 2 )
{
// 0 based indexing
System.out.print(moduloclass[i].get( 0 ) + 1 +
" " + moduloclass[i].get( 1 ));
return ;
}
}
} // Driver code public static void main(String args[])
{ int arr[] = { 7 , 3 , 5 , 2 };
int N = arr.length;
CheckSubarray(arr, N);
} } // This code is contributed by 29AjayKumar |
# Python 3 implementation of above approach # Function to check is there exists a # subarray whose sum is a multiple of N def CheckSubarray(arr, N):
# Prefix sum array to store cumulative sum
presum = [ 0 for i in range (N + 1 )]
# Single state dynamic programming
# relation for prefix sum array
for i in range ( 1 ,N + 1 ):
presum[i] = presum[i - 1 ] + arr[i - 1 ]
# Modulo class vector
moduloclass = [[]] * N
# Storing the index value in the modulo class vector
for i in range ( 1 ,N + 1 , 1 ):
moduloclass[presum[i] % N].append(i - 1 )
# If there exists a sub-array with
# starting index equal to zero
if ( len (moduloclass[ 0 ]) > 0 ):
print ( 0 + 1 ,moduloclass[ 0 ][ 0 ] + 2 )
return
for i in range ( 1 ,N):
# In this class, there are more than two presums%N
# Hence difference of any two subarrays would be a
# multiple of N
if ( len (moduloclass[i]) > = 2 ):
# 0 based indexing
print (moduloclass[i][ 0 ] + 1 ,moduloclass[i][ 1 ])
return
# Driver code if __name__ = = '__main__' :
arr = [ 7 , 3 , 5 , 2 ]
N = len (arr)
CheckSubarray(arr, N)
# This code is contributed by # Surendra_Gangwar |
// C# implementation of the approach using System;
using System.Collections.Generic;
class GFG
{ // Function to check is there exists a // subarray whose sum is a multiple of N static void CheckSubarray( int []arr, int N)
{ // Prefix sum array to store cumulative sum
int [] presum = new int [N + 1];
// Single state dynamic programming
// relation for prefix sum array
for ( int i = 1; i <= N; i += 1)
{
presum[i] = presum[i - 1] + arr[i - 1];
}
// Modulo class vector
List< int >[] moduloclass = new List< int >[N];
for ( int i = 0; i < N; i += 1)
{
moduloclass[i] = new List< int >();
}
// Storing the index value
// in the modulo class vector
for ( int i = 1; i <= N; i += 1)
{
moduloclass[presum[i] % N].Add(i - 1);
}
// If there exists a sub-array with
// starting index equal to zero
if (moduloclass[0].Count > 0)
{
Console.Write(0 + " " +
moduloclass[0][0]);
return ;
}
for ( int i = 1; i < N; i += 1)
{
// In this class, there are more than
// two presums%N. Hence difference of
// any two subarrays would be a multiple of N
if (moduloclass[i].Count >= 2)
{
// 0 based indexing
Console.Write(moduloclass[i][0] + 1 +
" " + moduloclass[i][1]);
return ;
}
}
} // Driver code public static void Main(String []args)
{ int []arr = {7, 3, 5, 2};
int N = arr.Length;
CheckSubarray(arr, N);
} } // This code is contributed by Rajput-Ji |
<script> // Javascript implementation of above approach // Function to check is there exists a // subarray whose sum is a multiple of N function CheckSubarray(arr, N)
{ // Prefix sum array to store cumulative sum
let presum = new Array(N + 1);
for (let i = 0; i < (N + 1); i++)
presum[i] = 0;
// Single state dynamic programming
// relation for prefix sum array
for (let i = 1; i <= N; i += 1)
{
presum[i] = presum[i - 1] + arr[i - 1];
}
// Modulo class vector
let moduloclass = new Array(N);
for (let i = 0; i < N; i += 1)
{
moduloclass[i] = [];
}
// Storing the index value
// in the modulo class vector
for (let i = 1; i <= N; i += 1)
{
moduloclass[presum[i] % N].push(i - 1);
}
// If there exists a sub-array with
// starting index equal to zero
if (moduloclass[0].length > 0)
{
document.write(0 + " " +
moduloclass[0][0]);
return ;
}
for (let i = 1; i < N; i += 1)
{
// In this class, there are more than
// two presums%N. Hence difference of
// any two subarrays would be a multiple of N
if (moduloclass[i].length >= 2)
{
// 0 based indexing
document.write(moduloclass[i][0] + 1 +
" " + moduloclass[i][1]);
return ;
}
}
} // Driver code let arr = [ 7, 3, 5, 2 ]; let N = arr.length; CheckSubarray(arr, N); // This code is contributed by unknown2108 </script> |
1 2
Time Complexity: O(n)
Auxiliary Space: O(n)