📜  在N个整数的数组中找到一个非空的子集,以使子集的元素之和可被N整除

📅  最后修改于: 2021-05-06 21:33:55             🧑  作者: Mango

给定一个由N个整数组成的数组,任务是找到一个非空子集,以使该子集的元素之和可被N整除。输出任何此类子集及其大小和元素的索引(基于1的索引)。原始数组(如果存在)。
先决条件:鸽洞原理
例子:

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 

天真的方法将是通过使用给定数组的幂集来生成所有可能的子集,计算它们各自的总和,并检查总和是否可被N整除。
时间复杂度: O(2 N * N),O(2 N )用于生成所有子集,O(N)用于计算每个子集的总和。
高效的方法:在考虑前缀求和时,我们获得:

由于存在(N)个前缀和值和N个可能的残基(N,0,1,2…N-2,N-1)。因此,根据信鸽原理,总会存在一个连续的子段,其子和总和相等。如果在任何情况下都使用前缀L ,则前L个索引将给出该子集。
下面是上述方法的实现:

C++
// CPP Program to find Non empty
// subset such that its elements' sum
// is divisible by N
#include 
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 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 mp =
                new HashMap();
 
    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
}


输出:
2
1 2

时间复杂度: O(N),其中N是数组的大小。