题目描述
给定整数数组 A,每次 move 操作将会选择任意 A[i],并将其递增 1。
返回使 A 中的每个值都是唯一的最少操作次数。
示例 1:
输入:[1,2,2]
输出:1
解释:经过一次 move 操作,数组将变为 [1, 2, 3]。
示例 2:
输入:[3,2,1,2,1,7]
输出:6
解释:经过 6 次 move 操作,数组将变为 [3, 4, 1, 2, 5, 7]。
可以看出 5 次或 5 次以下的 move 操作是不能让数组的每个值唯一的。
题目分析
通俗理解:就是让给的数组中的数各不相同,问移动代价
难点:测试用例特别大,容易超出时间限制
思路:**如果有两个x,就要在x之后找一个数y放另一个,y-x就是这个数造成的移动代价。**如果找到y就好办了,但是y的寻找要依赖后面的数字,所以还是要保证从前往后的情况下一遍找好y。
重点:其实我们求的是总的move值,不管是2->4,3->5还是2->5,3->4总的move值都是相等的,move =(y1-x1)+(y2-x2)= (y1+y2)-(x1+x2),从小到大遍历,x1x2我们知道个数和位置,所以设置一个变量来代表未来需要遇到多少个y,也可以理解为欠几个没加。这样遇到没有出现的数字就还一个。
具体实现:创建一个80000大小的数组(考虑四万个四万的情况),存相同数的个数,然后从小到大遍历,找到需要填充的位置。
代码
class Solution {
public int minIncrementForUnique(int[] A) {
int[] m = new int[80000];
for(int i=0;i<A.length;++i)
{
++m[A[i]];
}
int o = A.length;
int qian = 0;
int result = 0;
for(int i=0;i<80000;++i)
{
if(o<0)
{
break;
}
if(m[i]>0)
{
o -= m[i];
if(m[i]>1)
{
qian += m[i]-1;
result -= i*(m[i]-1);
}
}
else if(m[i]==0&&qian>0)
{
qian -= 1;
result += i;
}
}
return result;
}
}