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++
#include <bits/stdc++.h>
using namespace std;
int minIncrementForUnique( int A[], int n)
{
map< int , int > dict;
set< int > used;
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;
int ans = 0;
for ( auto entry : dict) {
int value = entry.first;
int freq = entry.second;
if (freq <= 1)
continue ;
int duplicates
= freq
- 1;
int cur = max(value + 1, maxUsed);
while (duplicates > 0) {
if (used.find(cur) == used.end()) {
ans += cur - value;
used.insert(cur);
duplicates--;
maxUsed = cur;
}
cur++;
}
}
return ans;
}
int main()
{
int A[] = { 3, 2, 1, 2, 1, 2, 6, 7 };
int n = sizeof (A) / sizeof (A[0]);
cout << minIncrementForUnique(A, n);
}
|
Java
import java.util.*;
class GFG {
static int minIncrementForUnique( int [] A)
{
TreeMap<Integer, Integer> dict
= new TreeMap<Integer, Integer>();
HashSet<Integer> used = new HashSet<Integer>();
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 ;
int ans = 0 ;
for (Map.Entry<Integer, Integer> entry :
dict.entrySet()) {
int value = entry.getKey();
int freq = entry.getValue();
if (freq <= 1 )
continue ;
int duplicates = freq - 1 ;
int cur = Math.max(value + 1 , maxUsed);
while (duplicates > 0 ) {
if (!used.contains(cur)) {
ans += cur - value;
used.add(cur);
duplicates--;
maxUsed = cur;
}
cur++;
}
}
return ans;
}
public static void main(String[] args)
{
int [] A = { 3 , 2 , 1 , 2 , 1 , 2 , 6 , 7 };
System.out.print(minIncrementForUnique(A));
}
}
|
Python3
import collections
def minIncrementForUnique(A):
count = collections.Counter(A)
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 ans
A = [ 3 , 2 , 1 , 2 , 1 , 7 ]
print (minIncrementForUnique(A))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int minIncrementForUnique( int []A)
{
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);
}
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 ans;
}
public static void Main(String[] args)
{
int []A = {3, 2, 1, 2, 1, 7};
Console.Write(minIncrementForUnique(A));
}
}
|
Javascript
function minIncrementForUnique(A)
{
let mpp = {};
for ( var i of A)
{
if (mpp.hasOwnProperty(i))
mpp[i] = mpp[i] + 1;
else
mpp[i] = 1;
}
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 ans;
}
let A = [ 3, 2, 1, 2, 1, 7 ];
console.log(minIncrementForUnique(A));
|
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++
#include<iostream>
#include<algorithm>
using namespace std;
int minIncrementForUnique( int A[], int n) {
sort(A,A+n);
int ops = 0;
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 ops;
}
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;
}
|
Java
import java.util.Arrays;
public class MinIncrementForUnique {
public static int minIncrementForUnique( int [] A) {
Arrays.sort(A);
int ops = 0 ;
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 ops;
}
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));
}
}
|
Python3
def minIncrementForUnique(A):
A.sort()
ops = 0
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 ops
A = [ 3 , 2 , 1 , 2 , 1 , 7 ]
print ( "Minimum number of increment operations required: " , minIncrementForUnique(A))
|
C#
using System;
using System.Linq;
class MinIncrementForUnique
{
public static int minIncrementForUnique( int [] A)
{
Array.Sort(A);
int ops = 0;
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 ops;
}
public static void Main()
{
int [] A = { 3, 2, 1, 2, 1, 7 };
Console.WriteLine( "Minimum number of increment operations required: " + minIncrementForUnique(A));
}
}
|
Javascript
function minIncrementForUnique(A) {
A.sort((a, b) => a - b);
let ops = 0;
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 ops;
}
const A = [3, 2, 1, 2, 1, 7];
console.log(`Minimum number of increment operations required: ${minIncrementForUnique(A)}`);
|
Output
Minimum number of increment operations required: 6
Time Complexity :- O(n*logn)
Space Complexity :- O(1)