给定N个整数的数组arr []和一个整数M ,其中N%M = 0 。任务是找到使数组c 0 = c 1 =….. = c M – 1 = N / M所需在数组上执行的最小操作数,其中c r是给定数组中的元素数当除以M时,余数为r 。在每个操作中,任何数组元素都可以增加1 。
例子:
Input: arr[] = {1, 2, 3}, M = 3
Output: 0
After performing the modulus operation on the given array, the array becomes {0, 1, 2}
And count of c0 = c1 = c2 = n / m = 1.
So, no any additional operations are required.
Input: arr[] = {3, 2, 0, 6, 10, 12}, M = 3
Output: 3
After performing the modulus operation on the given array, the array becomes {0, 2, 0, 0, 1, 0}
And count of c0 = 4, c1 = 1 and c2 = 1. To make c0 = c1 = c2 = n / m = 2.
Add 1 to 6 and 2 to 12 then the array becomes {3, 2, 0, 7, 10, 14} and c0 = c1 = c2 = n / m = 2.
方法:对于从0到m – 1的每个i ,找到数组中所有与i取模m一致的元素,并将它们的索引存储在列表中。另外,创建一个称为extra的向量,并使k = n / m 。
我们必须从0循环到m – 1两次。对于从0到m – 1的每个i ,如果列表中的元素多于k ,请从此列表中删除多余的元素,并将其添加到多余的元素中。相反,如果元素少于k,则从矢量多余的元素中删除最后几个元素。对于每个删除的索引idx ,将arr [idx]增加(i – arr [idx])%m 。
显然,在前m次迭代之后,每个列表的大小最多为k,而在m次迭代之后,所有列表的大小都相同,即k 。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
// Function to return the minimum
// number of operations required
int minOperations(int n, int a[], int m)
{
int k = n / m;
// To store modulos values
vector > val(m);
for (int i = 0; i < n; ++i) {
val[a[i] % m].push_back(i);
}
long long ans = 0;
vector > extra;
for (int i = 0; i < 2 * m; ++i) {
int cur = i % m;
// If it's size greater than k
// it needed to be decreased
while (int(val[cur].size()) > k) {
int elem = val[cur].back();
val[cur].pop_back();
extra.push_back(make_pair(elem, i));
}
// If it's size is less than k
// it needed to be increased
while (int(val[cur].size()) < k && !extra.empty()) {
int elem = extra.back().first;
int mmod = extra.back().second;
extra.pop_back();
val[cur].push_back(elem);
ans += i - mmod;
}
}
return ans;
}
// Driver code
int main()
{
int m = 3;
int a[] = { 3, 2, 0, 6, 10, 12 };
int n = sizeof(a) / sizeof(a[0]);
cout << minOperations(n, a, m);
return 0;
}
Java
// Java implementation of the approach
import java.util.*;
class GFG{
static class pair
{
int first, second;
public pair(int first, int second)
{
this.first = first;
this.second = second;
}
}
// Function to return the minimum
// number of operations required
static int minOperations(int n, int a[], int m)
{
int k = n / m;
// To store modulos values
@SuppressWarnings("unchecked")
Vector []val = new Vector[m];
for(int i = 0; i < val.length; i++)
val[i] = new Vector();
for(int i = 0; i < n; ++i)
{
val[a[i] % m].add(i);
}
long ans = 0;
Vector extra = new Vector<>();
for(int i = 0; i < 2 * m; ++i)
{
int cur = i % m;
// If it's size greater than k
// it needed to be decreased
while ((val[cur].size()) > k)
{
int elem = val[cur].lastElement();
val[cur].removeElementAt(val[cur].size() - 1);
extra.add(new pair(elem, i));
}
// If it's size is less than k
// it needed to be increased
while (val[cur].size() < k && !extra.isEmpty())
{
int elem = extra.get(extra.size() - 1).first;
int mmod = extra.get(extra.size() - 1).second;
extra.remove(extra.size() - 1);
val[cur].add(elem);
ans += i - mmod;
}
}
return (int)ans;
}
// Driver code
public static void main(String[] args)
{
int m = 3;
int a[] = { 3, 2, 0, 6, 10, 12 };
int n = a.length;
System.out.print(minOperations(n, a, m));
}
}
// This code is contributed by Princi Singh
Python3
# Python3 implementation of the approach
# Function to return the minimum
# number of operations required
def minOperations(n, a, m):
k = n // m
# To store modulos values
val = [[] for i in range(m)]
for i in range(0, n):
val[a[i] % m].append(i)
ans = 0
extra = []
for i in range(0, 2 * m):
cur = i % m
# If it's size greater than k
# it needed to be decreased
while len(val[cur]) > k:
elem = val[cur].pop()
extra.append((elem, i))
# If it's size is less than k
# it needed to be increased
while (len(val[cur]) < k and
len(extra) > 0):
elem = extra[-1][0]
mmod = extra[-1][1]
extra.pop()
val[cur].append(elem)
ans += i - mmod
return ans
# Driver code
if __name__ == "__main__":
m = 3
a = [3, 2, 0, 6, 10, 12]
n = len(a)
print(minOperations(n, a, m))
# This code is contributed by Rituraj Jain
C#
// C# implementation of the
// above approach
using System;
using System.Collections.Generic;
class GFG{
public class pair
{
public int first,
second;
public pair(int first,
int second)
{
this.first = first;
this.second = second;
}
}
// Function to return the minimum
// number of operations required
static int minOperations(int n,
int []a,
int m)
{
int k = n / m;
// To store modulos values
List []val =
new List[m];
for(int i = 0;
i < val.Length; i++)
val[i] = new List();
for(int i = 0; i < n; ++i)
{
val[a[i] % m].Add(i);
}
long ans = 0;
List extra =
new List();
for(int i = 0;
i < 2 * m; ++i)
{
int cur = i % m;
// If it's size greater than k
// it needed to be decreased
while ((val[cur].Count) > k)
{
int elem = val[cur][val[cur].Count - 1];
val[cur].RemoveAt(val[cur].Count - 1);
extra.Add(new pair(elem, i));
}
// If it's size is less than k
// it needed to be increased
while (val[cur].Count < k &&
extra.Count != 0)
{
int elem = extra[extra.Count - 1].first;
int mmod = extra[extra.Count - 1].second;
extra.RemoveAt(extra.Count - 1);
val[cur].Add(elem);
ans += i - mmod;
}
}
return (int)ans;
}
// Driver code
public static void Main(String[] args)
{
int m = 3;
int []a = {3, 2, 0, 6, 10, 12};
int n = a.Length;
Console.Write(minOperations(n, a, m));
}
}
// This code is contributed by Princi Singh
3