Open In App

Find a subarray whose sum is divisible by size of the array

Last Updated : 31 May, 2022
Comments
Improve
Suggest changes
Like Article
Like
Report

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)


Next Article

Similar Reads