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

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

Below is the implementation of above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

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

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// 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);
}
}

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

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

chevron_right


Output:

2
1 2

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



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.



Improved By : AnkitRai01