[leetCode]945.使数组唯一的最小增量
排序 + 遍历计数
我的思路是对数组进行排序,然后对排序后的数组从前向后进行遍历。如果出现重复数字则将其递增,同时记录操作次数。
class Solution {
public int minIncrementForUnique(int[] A) {
int count = 0;
Arrays.sort(A);
for(int i = 0; i < A.length; i++){
int j = i + 1;
while(j < A.length && A[j] <= A[i]){
++A[j];
++count;
}
}
return count;
}
}
计数
首先统计A中重复数字出现的次数、
- 如果该数字x出现两次以上则记录多余数字出现的次数,并减去这些多余数字
- 如果该数字未出现则加上该数字
class Solution {
public int minIncrementForUnique(int[] A) {
//定义一个数组对A中重复数字进行计数,由于A<=40000,最坏情况下A中数字会递增到79999;
int[] count = new int[80000];
for( int x : A)count[x]++;
int ans = 0;//记录答案
int taken = 0;//记录多余数字出现的次数
for(int x = 0; x < count.length; x++){
if(count[x]>=2){//如果该数字在A中重复出现
//多余数字出现的次数为:
taken += count[x] - 1;
//ans先减去这些多余重复的数字
ans -= x *(count[x] - 1);
}else if(taken > 0 && count[x] == 0){//如果该数字为出现过
//ans加上该未出现过的数字
ans+=x;
//多余数字减1
--taken;
}
}
return ans;
}
}
排序
对数组进行排序,将多余数字变为区间中的数字
class Solution {
public int minIncrementForUnique(int[] A) {
//对数组进行排序
Arrays.sort(A);
int ans = 0;//记录答案
int taken = 0;//记录多余的数字
for(int i = 1; i < A.length; i++){
if(A[i] == A[i-1]){
//多余的数字加1,
++taken;
//ans减去该重复数字
ans -= A[i];
}else {//i指针已经跳过了重复数字,区间{A[i-1]+1~A[i]-1}中的数字是未出现过的,将重复数字变为次区间的数
int give = Math.min(A[i] - A[i-1] - 1, taken);//区间范围有限因此应取最小值
//give*(give+1)/2为等差数列求和
ans+= give * (A[i-1]) + give*(give+1)/2;
taken -=give;
}
}
if(taken > 0){//如果还有多余的数字则变为区间{A[A.length-1]] +1~正无穷}之间的数字
ans += taken * (A[A.length-1]) + taken*(taken+1)/2;
}
return ans;
}
}