Find a subarray whose sum is divisible by size of the array (original) (raw)

Last Updated : 31 May, 2022

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

`

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

`

Time Complexity: O(n)

Auxiliary Space: O(n)