Thursday, January 16, 2025
Google search engine
HomeData Modelling & AIFind a subarray whose sum is divisible by size of the array

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++




// 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>


Output: 

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:

  1. If one of the above prefix sums is a multiple of N then print the ith subarray indices.
  2. 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>


Output: 

1 2

 

Time Complexity: O(n)

Auxiliary Space: O(n)

Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

RELATED ARTICLES

Most Popular

Recent Comments