Operaciones de incremento mínimo para hacer que Array sea único

Dada una array A[] de enteros. En un movimiento, puede elegir cualquier elemento A[i] e incrementarlo en 1. La tarea es devolver el número mínimo de movimientos necesarios para que cada valor en la array A[] sea único.
Ejemplos
 

Input: A[] = [3, 2, 1, 2, 1, 7]
Output: 6
Explanation:  After 6 moves, the array could be 
[3, 4, 1, 2, 5, 7].
It can be shown that it is impossible for the array 
to have all unique values with 5 or less moves.

Input: A[] = [1, 2, 2]
Output: 1
Explanation: After 1 move [2 -> 3], the array could be [1, 2, 3].

Una solución simple para hacer que cada valor duplicado sea único es seguir incrementándolo repetidamente hasta que no sea único. Sin embargo, podríamos hacer mucho trabajo extra, si tenemos una array de todos unos.
Entonces, lo que podemos hacer en su lugar es evaluar cuáles deberían ser nuestros incrementos. Si, por ejemplo, tenemos [1, 1, 1, 3, 5], no necesitamos procesar todos los incrementos de 1 duplicados. Podríamos tomar dos unos (tomados = [1, 1]) y continuar procesando. Siempre que encontremos un lugar vacío (valor no utilizado) como 2 o 4, podemos recuperar que nuestro incremento será 2-1, 4-1 respectivamente.
Por lo tanto, primero contamos los valores y para cada posible valor X en la array: 
 

  • Si hay 2 o más valores X en A, guarde los valores duplicados adicionales para incrementarlos más tarde.
  • Si hay 0 valores X en A, entonces un valor guardado se incrementa a X.

A continuación se muestra la implementación del enfoque anterior: 
 

Java

// Java Implementation of above approach
import java.util.*;
 
class GFG {
 
    // function to find minimum increment required
    static int minIncrementForUnique(int[] A)
    {
        // collect frequency of each element
        TreeMap<Integer, Integer> dict
            = new TreeMap<Integer, Integer>();
        HashSet<Integer> used = new HashSet<Integer>();
 
      // Load Frequency Map (Element -> Count) and Used Set
        for (int i : A) {
            if (dict.containsKey(i))
                dict.put(i, dict.get(i) + 1);
            else {
                dict.put(i, 1);
                used.add(i);
            }
        }
 
        int maxUsed = 0; // Works for +ve numbers
        int ans = 0;
 
        for (Map.Entry<Integer, Integer> entry :
             dict.entrySet()) {
 
            int value = entry.getKey();
            int freq = entry.getValue();
 
            if (freq <= 1) //If not a duplicate, skip
                continue;
 
            int duplicates = freq - 1; // Number of duplicates 1 less than count
           
          // Start with next best option for this duplicate:
          // CurNum + 1 or an earlier maximum number that has been used
            int cur = Math.max(value + 1, maxUsed);
            while (duplicates > 0) {
                if (!used.contains(cur)) {
                    ans += cur - value; // Number of increments = Available Spot - Duplicate Value
                    used.add(cur);
                    duplicates--;
                    maxUsed = cur;
                }
                cur++;
            }
        }
 
        // return answer
        return ans;
    }
 
    // Driver code
 
    public static void main(String[] args)
    {
        int[] A = { 3, 2, 1, 2, 1, 2, 6, 7 };
        System.out.print(minIncrementForUnique(A));
    }
}
 
// This code is contributed by Aditya

Python3

# Python3 Implementation of above approach
import collections
 
# function to find minimum increment required
def minIncrementForUnique(A):
 
    # collect frequency of each element
    count = collections.Counter(A)
 
    # array of unique values taken
    taken = []
 
    ans = 0
 
    for x in range(100000):
        if count[x] >= 2:
            taken.extend([x] * (count[x] - 1))
        elif taken and count[x] == 0:
            ans += x - taken.pop()
 
    # return answer
    return ans
 
# Driver code
A = [3, 2, 1, 2, 1, 7]
print(minIncrementForUnique(A))

C#

// C# Implementation of above approach
using System;
using System.Collections.Generic;
 
class GFG
{
  
// function to find minimum increment required
static int minIncrementForUnique(int []A)
{
  
    // collect frequency of each element
    Dictionary<int,int> mpp = new Dictionary<int,int>();
  
    foreach(int i in A)
    {
        if(mpp.ContainsKey(i))
            mpp[i] = mpp[i] + 1;
        else
            mpp.Add(i, 1);
    }
  
    // array of unique values taken
    List<int> taken = new List<int>();
  
    int ans = 0;
  
    for (int x = 0; x < 100000; x++)
    {
        if (mpp.ContainsKey(x) && mpp[x] >= 2)
            taken.Add(x * (mpp[x] - 1));
        else if(taken.Count > 0 &&
                ((mpp.ContainsKey(x) &&
                mpp[x] == 0)||!mpp.ContainsKey(x)))
        {
            ans += x - taken[taken.Count - 1];
            taken.RemoveAt(taken.Count - 1);
        }
    }
  
    // return answer
    return ans;
}
  
// Driver code
public static void Main(String[] args)
{
  
    int []A = {3, 2, 1, 2, 1, 7};
      
    Console.Write(minIncrementForUnique(A));
}
}
 
// This code contributed by PrinciRaj1992
Producción

12

Complejidad de tiempo: O(n*log(n))
Espacio auxiliar: O(n)
 

Publicación traducida automáticamente

Artículo escrito por Sanjit_Prasad y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *