📜  最小增量操作以使数组唯一

📅  最后修改于: 2021-04-27 22:19:26             🧑  作者: Mango

给定整数数组A []。一键移动可以选择任意元素A [i],并将其递增1。任务是返回使数组A []中的每个值唯一所需的最小移动数。
例子

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


使每个重复值唯一的一种简单解决方案是不断重复增加它,直到它不是唯一的为止。但是,如果我们有一个数组,那么我们可能会做很多额外的工作。
因此,我们可以做的是评估我们的增量应该是多少。例如,如果我们有[1、1、1、3、5],则不需要处理重复的1的所有增量。我们可以取两个(取= [1,1])并继续处理。每当我们找到一个空的(未使用的值)位置(例如2或4)时,我们都可以恢复到增量分别为2-1、4-1。
因此,我们首先对值进行计数,并对数组中每个可能的值X进行计数:

  • 如果A中有两个或两个以上的值X,请保存多余的重复值,以便以后增加。
  • 如果A中有0个值X,则保存的值将递增到X。

下面是上述方法的实现:

CPP
// C++ Implementation of above approach
#include 
 
using namespace std;
 
// function to find minimum increment required
int minIncrementForUnique(vector A)
{
 
    // collect frequency of each element
    unordered_map mpp;
 
    for(int i:A) mpp[i]++;
 
    // taken is to keep count
    // of duplicate items
    int taken=0, ans=0;
 
    for (int x = 0; x < 100000; x++)
    {
         
        // If number is present
          // multiple times
          if (mpp[x] >= 2){
          taken += mpp[x]-1;
          ans -= x*(mpp[x]-1);
        }
           
          // If there is no x in the array
        else if(taken > 0 and mpp[x] == 0)
        {
            ans += x;
            taken--;
        }
    }
 
    // return answer
    return ans;
}
 
// Driver code
int main()
{
    vector A = {3, 2, 1, 2, 1, 7};
     
    // Function Call
    cout << minIncrementForUnique(A);
     
    return 0;
}
 
// This code is contributed by mohit kumar 29


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
    HashMap mpp = new HashMap();
 
    for(int i:A)
    {
        if(mpp.containsKey(i))
            mpp.put(i, mpp.get(i) + 1);
        else
            mpp.put(i, 1);
    }
 
    // array of unique values taken
    Vector taken =
                        new Vector();
 
    int ans = 0;
 
    for (int x = 0; x < 100000; x++)
    {
         
          // If number is present
          // multiple times
          if (mpp.containsKey(x) && mpp.get(x) >= 2)
        {
            taken.add(x * (mpp.get(x)- 1));
        }
       
          // If there is no x in the array
        else if(taken.size() > 0 &&
                ((mpp.containsKey(x) &&
                mpp.get(x) == 0)||!mpp.containsKey(x)))
        {
            ans += x - taken.get(taken.size() - 1);
            taken.remove(taken.size() - 1);
        }
    }
 
    // return answer
    return ans;
}
 
// Driver code
public static void main(String[] args)
{
 
    int []A = {3, 2, 1, 2, 1, 7};
     
    System.out.print(minIncrementForUnique(A));
}
}
 
// This code is contributed by Rajput-Ji


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 mpp = new Dictionary();
  
    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 taken = new List();
  
    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


输出:
6


时间复杂度: O(N)