参考了,leetcode官方题解的方法,使用计数的方式
算法
首先统计出每个数出现的次数,然后从小到大遍历每个数 x
:
如果 x
出现了两次以上,就将额外出现的数记录下来(例如保存到一个列表中);
如果 x
没有出现过,那么在记录下来的数中选取一个 v
,将它增加到 x
,需要进行的操作次数为 x - v
。
我们还可以对该算法进行优化,使得我们不需要将额外出现的数记录下来。还是以 [1, 1, 1, 1, 3, 5]
为例,当我们发现有 3
个重复的 1
时,我们先将操作次数减去 1 + 1 + 1
。接下来,当我们发现 2
,4
和 6
都没有出现过时,我们依次将操作次数增加 2
,4
和 6
.
注意事项
虽然 A[i]
的范围为 [0, 40000)
,但我们有可能会将数据递增到 40000
的两倍 80000
。这是因为在最坏情况下,数组 A 中有 40000
个 40000
,这样要使得数组值唯一,需要将其递增为 [40000, 40001, ..., 79999]
,因此用来统计的数组需要开到 80000
。
class Solution {
public int minIncrementForUnique(int[] A) {
int[] count = new int[80001];
for (int i=0;i<A.length;i++)
count[A[i]]++;
int repeat = 0;//count[i]大于等于2的位置
int empty = 0;//count[i]为0 的位置
int cnt = 0;//重复数字的个数
for (int i = 0; i <= 80000; i++) {
if(count[i] >= 2){
repeat += (count[i]-1) * i;
cnt+= count[i] - 1;
}else if(count[i] == 0 && cnt > 0){
empty += i;
cnt--;
}
}
return empty - repeat;
}
public static void main(String[] args) {
int[] arr = {2,2,2,1};
System.out.println(new Solution().minIncrementForUnique(arr));
}
}