给定一个由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)用于计算每个子集的总和。
高效的方法:在考虑前缀求和时,我们获得:
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.
由于存在(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是数组的大小。