Open In App

Find a non empty subset in an array of N integers such that sum of elements of subset is divisible by N

Last Updated : 06 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array of N integers, the task is to find a non-empty subset such that the sum of elements of the subset is divisible by N. Output any such subset with its size and the indices(1-based indexing) of elements in the original array if it exists. 
Prerequisites: Pigeonhole Principle
Examples:

Input: arr[] = { 2, 3, 7, 1, 9 }
Output: 2
        1 2
The required subset is { 2, 3 } whose indices are 1 and 2.


Input: arr[] = {2, 11, 4}
Output: 2
        2 3 

A naive approach will be to generate all possible subsets by using the Power Set of the given array, calculate their respective sums and check if the sum is divisible by N. 
Time Complexity: O(2N * N), O(2N) for generating all subsets, and O(N) for calculating the sum of every subset.
Efficient Approach: On considering Prefix Sums, we obtain:
 

prefixSum0 = arr0
prefixSum1 = arr0 + arr1
prefixSum2 = arr0 + arr1 + arr2

prefixSumN = arr0 + arr1 + arr2 + … + arrN
It can be seen easily that arrL + arrL+1 + … + arrR (L ? R) equals to prefixSumR – 
prefixSumL-1. If the sum of any contiguous subsegment is divisible by N, then it 
means the residue upon taking modulo N of prefixSumR – prefixSumL-1 
is zero, i.e.
(prefixSumR – prefixSumL-1) % N = 0;
Splitting the modulo, 
prefixSumR % N – prefixSumL-1 % N = 0 
prefixSumR % N = prefixSumL-1 % N. 

Since there are (N) values of prefixSums and N possible residues for N (0, 1, 2 … N-2, N-1). Hence, according to the pigeonhole principle there always exists a contiguous subsegment whose prefixSum extremities are equal. If at any instance, prefixL, then the first L indexes will give the subset. 

Steps were to solve the above approach:

  • Initialize an empty unordered_map mp that will store the residue of the prefix sum and its index.
  • Initialize a variable sum to 0.
  • Iterate over the array arr with index i from 0 to N-1:
    • Add the value of arr[i] to sum.
    • Take the residue of sum with N, i.e., sum = sum % N.
    • If sum is equal to 0:
      • Print the size of the subsegment which is (i+1).
      • Print the indices of the subsegment which are from 0 to i.
      • Return from the function.
    • If sum is already in the map:
      • Print the size of the subsegment which is (i – mp[sum]).
      • Print the indices of the subsegment which are from (mp[sum]+1) to i.
      • Return from the function.
    • Else mp[sum]=i.

Below is the code to implement the above approach: 
 

C++




// CPP Program to find Non empty
// subset such that its elements' sum
// is divisible by N
#include <bits/stdc++.h>
using namespace std;
 
// Function to print the subset index and size
void findNonEmptySubset(int arr[], int N)
{
 
    // Hash Map to store the indices of residue upon
    // taking modulo N of prefixSum
    unordered_map<int, int> mp;
 
    int sum = 0;
    for (int i = 0; i < N; i++) {
        // Calculating the residue of prefixSum
        sum = (sum + arr[i]) % N;
 
        // If the pre[i]%n==0
        if (sum == 0) {
            // print size
            cout << i + 1 << endl;
 
            // Print the first i indices
            for (int j = 0; j <= i; j++)
                cout << j + 1 << " ";
            return;
        }
 
        // If this sum was seen earlier, then
        // the contiguous subsegment has been found
        if (mp.find(sum) != mp.end()) {
            // Print the size of subset
            cout << (i - mp[sum]) << endl;
 
            // Print the indices of contiguous subset
            for (int j = mp[sum] + 1; j <= i; j++)
                cout << j + 1 << " ";
 
            return;
        }
        else
            mp[sum] = i;
    }
}
 
// Driver Code
int main()
{
    int arr[] = { 2, 3, 7, 1, 9 };
    int N = sizeof(arr) / sizeof(arr[0]);
 
    findNonEmptySubset(arr, N);
 
    return 0;
}


Java




// Java Program to find Non
// empty subset such that
// its elements' sum is
// divisible by N
import java.io.*;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Map;
import java.lang.*;
 
class GFG
{
     
// Function to print the
// subset index and size
static void findNonEmptySubset(int arr[],
                               int N)
{
 
    // Hash Map to store the
    // indices of residue upon
    // taking modulo N of prefixSum
    HashMap<Integer, Integer> mp =
                new HashMap<Integer, Integer>();
 
    int sum = 0;
    for (int i = 0; i < N; i++)
    {
        // Calculating the
        // residue of prefixSum
        sum = (sum + arr[i]) % N;
 
        // If the pre[i]%n==0
        if (sum == 0)
        {
            // print size
            System.out.print(i + 1 + "\n");
 
            // Print the first i indices
            for (int j = 0; j <= i; j++)
                System.out.print(j + 1 + " ");
            return;
        }
 
        // If this sum was seen
        // earlier, then the
        // contiguous subsegment
        // has been found
        if (mp.containsKey(sum) == true)
        {
            // Print the size of subset
            System.out.println((i -
                              mp.get(sum)));
 
            // Print the indices of
            // contiguous subset
            for (int j = mp.get(sum) + 1;
                     j <= i; j++)
                System.out.print(j + 1 + " ");
 
            return;
        }
        else
            mp.put(sum,i);
    }
}
 
// Driver Code
public static void main(String[] args)
{
    int arr[] = { 2, 3, 7, 1, 9 };
    int N = arr.length;
 
    findNonEmptySubset(arr, N);
}
}


Python3




# Python3 Program to find Non
# empty subset such that its
# elements' sum is divisible
# by N
 
# Function to print the subset
# index and size
def findNonEmptySubset(arr, N):
 
    # Hash Map to store the indices
    # of residue upon taking modulo
    # N of prefixSum
    mp = {}
 
    Sum = 0
    for i in range(N):
        # Calculating the residue of
        # prefixSum
        Sum = (Sum + arr[i]) % N
 
        # If the pre[i]%n==0
        if (Sum == 0) :
            # print size
            print(i + 1)
 
            # Print the first i indices
            for j in range(i + 1):
                print(j + 1, end = " ")
            return
 
        # If this sum was seen earlier,
        # then the contiguous subsegment
        # has been found
        if Sum in mp :
           
            # Print the size of subset
            print((i - mp[Sum]))
 
            # Print the indices of contiguous
            # subset
            for j in range(mp[Sum] + 1,
                           i + 1):
                print(j + 1, end = " ")
 
            return
        else:
            mp[Sum] = i
             
# Driver code
arr = [2, 3, 7, 1, 9]
N = len(arr)
findNonEmptySubset(arr, N)
 
# This code is contributed by divyeshrabadiya07


C#




// C# Program to find Non
// empty subset such that
// its elements' sum is
// divisible by N
 
using System;
using System.Collections ;
 
class GFG
{    
    // Function to print the
    // subset index and size
    static void findNonEmptySubset(int []arr, int N)
    {
     
        // Hash Map to store the
        // indices of residue upon
        // taking modulo N of prefixSum
        Hashtable mp = new Hashtable();
     
        int sum = 0;
        for (int i = 0; i < N; i++)
        {
            // Calculating the
            // residue of prefixSum
            sum = (sum + arr[i]) % N;
     
            // If the pre[i]%n==0
            if (sum == 0)
            {
                // print size
                Console.Write(i + 1 + "\n");
     
                // Print the first i indices
                for (int j = 0; j <= i; j++)
                    Console.Write(j + 1 + " ");
                return;
            }
     
            // If this sum was seen
            // earlier, then the
            // contiguous subsegment
            // has been found
            if (mp.ContainsKey(sum) == true)
            {
                // Print the size of subset
                    Console.WriteLine(i - Convert.ToInt32(mp[sum]));
     
                // Print the indices of
                // contiguous subset
                for (int j = Convert.ToInt32(mp[sum]) + 1;
                        j <= i; j++)
                        Console.Write(j + 1 + " ");
     
                return;
            }
            else
                mp.Add(sum,i);
        }
    }
     
    // Driver Code
    public static void Main()
    {
        int []arr = { 2, 3, 7, 1, 9 };
        int N = arr.Length;
     
        findNonEmptySubset(arr, N);
    }
    // This code is contributed by Ryuga
}


Javascript




<script>
// JavaScript Program to find Non empty
// subset such that its elements' sum
// is divisible by N
 
// Function to print the subset index and size
function findNonEmptySubset( arr , N)
{
 
    // Hash Map to store the indices of residue upon
    // taking modulo N of prefixSum
    var mp =new Map();
 
    var sum = 0;
    for (let i = 0; i < N; i++)
    {
     
        // Calculating the residue of prefixSum
        sum = (sum + arr[i]) % N;
 
        // If the pre[i]%n==0
        var str="";
        if (sum == 0)
        {
         
            // print size
            console.log(i + 1 );
 
            // Print the first i indices
            for (let j = 0; j <= i; j++)
                str+=j + 1 + " ";
            console.log(str);
            return;
        }
 
        // If this sum was seen earlier, then
        // the contiguous subsegment has been found
        if (mp.has(sum))
        {
         
            // Print the size of subset
            console.log(i - mp[sum]);
 
            // Print the indices of contiguous subset
            for (let j = mp[sum] + 1; j <= i; j++)
                str+=j + 1 + " ";
            console.log(str);
 
            return;
        }
        else
            mp[sum] = i;
    }
}
 
// Driver Code
var arr = new Array( 2, 3, 7, 1, 9 );
var N = arr.length;
 
findNonEmptySubset(arr, N);
 
// This code is contributed by ukasp. 
 
</script>


Output: 

2
1 2

 

Time Complexity: O(N), where N is the size of the array.
Auxiliary Space: O(N) 
 



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads