题目描述
给定整数数组 A,每次 move 操作将会选择任意 A[i],并将其递增 1。
返回使 A 中的每个值都是唯一的最少操作次数。
思路
- 暴力解法:从前到后遍历数组,利用Hash统计当前数字出现的次数,若不为0则该数字++直至该数字第一次出现。考虑到数组长度和值都不超过40000,则Hash数组的大小应该为80000,(考虑极限情况,所有数字都是40000)
- 先排序,然后从头到尾遍历,若当前数字==前一个数字,则count++, r若当前数字<前一个数字,count+=A[i-1]+1-A[i], A[i] = A[i-1]+1
- 计数排序法:遍历数组,并利用Hash统计数字出现的次数,同时找到数组中的最大值。遍历Hash数组,若Hash[i]>1,则将多的部分加到Hash[i+1]上,同时count也加上多的部分。最后不要忘了将Hash[max+1]的超过1的部分也要往前挪
代码
方法一:
class Solution {
public:
int minIncrementForUnique(vector<int>& A) {
if(A.size() < 2)
return 0;
vector<int> Hash(80000);
int count = 0;
for(int i = 0; i < A.size();i++)
{
if (Hash[A[i]] == 0)
Hash[A[i]]++;
else
{
int k = A[i];
while (Hash[k] != 0 && k<80001)
{
count++;
k++;
}
Hash[k]++;
}
}
return count;
}
};
方法二:
class Solution {
public:
int minIncrementForUnique(vector<int>& A) {
if(A.size() < 2)
return 0;
sort(A.begin(),A.end());
int count = 0;
for(int i = 1; i < A.size();i++)
{
if(A[i] == A[i-1])
{
count++;
A[i]++;
}
else if(A[i] < A[i-1])
{
count += A[i-1] + 1 - A[i];
A[i] = A[i-1]+1;
}
}
return count;
}
};
方法三:
class Solution {
public:
int minIncrementForUnique(vector<int>& A) {
if(A.size() < 2)
return 0;
int res = 0;
int max = -1;
vector<int> Hash(40000,0);
for(int i = 0 ; i < A.size(); i++)
{
Hash[A[i]]++;
if(A[i]>max) max = A[i];
}
for(int i = 0; i <= max;i++)
{
if(Hash[i] > 1)
{
int d = Hash[i] - 1;
Hash[i+1] += d;
res += d;
}
}
int d = Hash[max+1]-1;
res = res + d*(1+d)/2;
return res;
}
};