Open In App

Minimum Increment operations to make Array unique

Last Updated : 07 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array A[] of integers. In one move you can choose any element A[i], and increment it by 1. The task is to return the minimum number of moves needed to make every value in the array A[] unique.
Examples
 

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

 

A simple solution to make each duplicate value unique is to keep incrementing it repeatedly until it is not unique. However, we might do a lot of extra work, if we have an array of all ones.
So, what we can do instead is to evaluate what our increments should be. If for example, we have [1, 1, 1, 3, 5], we don’t need to process all the increments of duplicated 1’s. We could take two ones (taken = [1, 1]) and continue processing. Whenever we find an empty(unused value) place like 2 or 4 we can then recover that our increment will be 2-1, 4-1 respectively.
Thus, we first count the values and for each possible value X in the array: 
 

  • If there are 2 or more values X in A, save the extra duplicated values to increment later.
  • If there are 0 values X in A, then a saved value gets incremented to X.

Below is the implementation of the above approach: 
 

C++




// C++ Implementation of above approach
#include <bits/stdc++.h>
using namespace std;
 
// function to find minimum increment required
int minIncrementForUnique(int A[], int n)
{
   
    // collect frequency of each element
    map<int, int> dict;
    set<int> used;
 
    // Load Frequency Map (Element -> Count) and Used Set
    for (int x = 0; x < n; x++) {
        int i = A[x];
        if (dict[i] != 0)
            dict[i]++;
        else {
            dict[i] = 1;
            used.insert(i);
        }
    }
 
    int maxUsed = 0; // Works for +ve numbers
    int ans = 0;
 
    for (auto entry : dict) {
 
        int value = entry.first;
        int freq = entry.second;
 
        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 = max(value + 1, maxUsed);
        while (duplicates > 0) {
            if (used.find(cur) == used.end()) {
                ans += cur - value; // Number of increments
                                    // = Available Spot -
                                    // Duplicate Value
                used.insert(cur);
                duplicates--;
                maxUsed = cur;
            }
            cur++;
        }
    }
 
    // return answer
    return ans;
}
 
// Driver code
int main()
{
    int A[] = { 3, 2, 1, 2, 1, 2, 6, 7 };
    int n = sizeof(A) / sizeof(A[0]);
    cout << minIncrementForUnique(A, n);
}
 
// This code is contributed by Aditya


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


Javascript




// JavaScript Implementation of above approach
function minIncrementForUnique(A)
{
  
    // collect frequency of each element
    let mpp = {};
  
    for(var i of A)
    {
        if(mpp.hasOwnProperty(i))
            mpp[i] = mpp[i] + 1;
        else
            mpp[i] = 1;
    }
  
    // array of unique values taken
    let taken = [];
    let ans = 0;
    for (let x = 0; x < 100000; x++)
    {
        if (mpp.hasOwnProperty(x) && mpp[x] >= 2)
            taken.push([...new Array(mpp[x] - 1).fill(x)]);
        else if(taken.length > 0 &&
                ((mpp.hasOwnProperty(x) &&
                mpp[x] == 0)||!mpp.hasOwnProperty(x)))
        {
            ans += x - taken.pop();
        }
    }
  
    // return answer
    return ans;
}
 
// Driver code
let A = [ 3, 2, 1, 2, 1, 7 ];
console.log(minIncrementForUnique(A));
 
// This code is contributed by phasing17


Output

12

Time Complexity: O(n*log(n))
Auxiliary Space: O(n)
 

Another Approach:

This problem can be solved by sorting the array and then iterating through it, comparing each element to the previous element. If the current element is equal to the previous element, increment the current element until it is unique and increment the counter for the number of operations. After iterating through the array, return the counter.

Steps to solve this problem:

1. sort the array from 0 to n in increasing order.

2. declare a variable ops =0.

3. iterate through i=0 till n:

        *check if A[i] smaller than equal to A[i-1] than ops+=A[i-1]-A[i]+1 and A[i]=A[i-1]+1.

4. return ops.

Below is the implementation of the above approach:

C++




// C++ Implementation of above approach
#include<iostream>
#include<algorithm>
using namespace std;
 
// function to find minimum increment required
int minIncrementForUnique(int A[], int n) {
   
      // sort the array in increasing order
    sort(A,A+n);
   
      // counter for no of operations
    int ops = 0;
   
      // iterate over the array
    for (int i = 1; i < n; i++) {
        if (A[i] <= A[i-1]) {
            ops += A[i-1] - A[i] + 1;
            A[i] = A[i-1] + 1;
        }
    }
   
      // return no of operations required
    return ops;
}
 
// Driver code
int main() {
    int A[] = {3, 2, 1, 2, 1, 7};
    int n = sizeof(A)/sizeof(A[0]);
    cout << "Minimum number of increment operations required: " << minIncrementForUnique(A,n);
    return 0;
}
 
// This code is contributed by Jeetu


Java




// Java Implementation of above approach
import java.util.Arrays;
 
public class MinIncrementForUnique {
    // function to find minimum increment required
    public static int minIncrementForUnique(int[] A) {
       
          // sort the array in increasing order
        Arrays.sort(A);
       
          // counter for no of operations
        int ops = 0;
       
          // iterate over the array
        for (int i = 1; i < A.length; i++) {
            if (A[i] <= A[i-1]) {
                ops += A[i-1] - A[i] + 1;
                A[i] = A[i-1] + 1;
            }
        }
       
          // return no of operations required
        return ops;
    }
 
    // Driver code
    public static void main(String[] args) {
        int[] A = {3, 2, 1, 2, 1, 7};
        System.out.println("Minimum number of increment operations required: " + minIncrementForUnique(A));
    }
}
 
// This code is contributed by Jeetu


Python3




# Python3 Implementation of above approach
def minIncrementForUnique(A):
      # sort the array in increasing order
    A.sort()
     
    #counter for no of operations
    ops = 0
     
    # iterate over the array
    for i in range(1, len(A)):
        if A[i] <= A[i-1]:
            ops += A[i-1] - A[i] + 1
            A[i] = A[i-1] + 1
     
    #return no of operations required
    return ops
 
# Driver code
A = [3, 2, 1, 2, 1, 7]
print("Minimum number of increment operations required: ", minIncrementForUnique(A))
 
# This code is contributed by Jeetu


C#




// C# Implementation of above approach
using System;
using System.Linq;
 
class MinIncrementForUnique
{
      // function to find minimum increment required
    public static int minIncrementForUnique(int[] A)
    {
          // sort the array in increasing order
        Array.Sort(A);
       
          // counter for no of operations
        int ops = 0;
       
          // iterate over the array
        for (int i = 1; i < A.Length; i++)
        {
            if (A[i] <= A[i-1])
            {
                ops += A[i-1] - A[i] + 1;
                A[i] = A[i-1] + 1;
            }
        }
       
          // return no of operations required
        return ops;
    }
 
      // Driver code
    public static void Main()
    {
        int[] A = { 3, 2, 1, 2, 1, 7 };
        Console.WriteLine("Minimum number of increment operations required: " + minIncrementForUnique(A));
    }
}
 
// This code is contributed by Jeetu


Javascript




// JavaScript Implementation of above approach
function minIncrementForUnique(A) {
    // sort the array in increasing order
    A.sort((a, b) => a - b);
     
    // counter for no of operations
    let ops = 0;
     
    // iterate over the array
    for (let i = 1; i < A.length; i++) {
        if (A[i] <= A[i-1]) {
            ops += A[i-1] - A[i] + 1;
            A[i] = A[i-1] + 1;
        }
    }
     
    // return no of operations required
    return ops;
}
 
// Driver code
const A = [3, 2, 1, 2, 1, 7];
console.log(`Minimum number of increment operations required: ${minIncrementForUnique(A)}`);
 
// This code is contributed by Jeetu


Output

Minimum number of increment operations required: 6

Time Complexity :- O(n*logn)

Space Complexity :- O(1)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads