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++
// 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
// 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
# 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#
// 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.. |
Javascript
<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++
// 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
// 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 |
Python3
# 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#
// 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 |
Javascript
<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)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!