0x01.问题
给定整数数组
A
,每次 move 操作将会选择任意A[i]
,并将其递增1
。
返回使A
中的每个值都是唯一的最少操作次数。
输入示例:[3,2,1,2,1,7]
输出示例:6
解释:经过 6 次 move 操作,数组将变为 [3, 4, 1, 2, 5, 7]。
提示:0 <= A.length <= 40000
0 <= A[i] < 40000
C++函数形式为 int minIncrementForUnique(vector<int>& A)
0x02.简要分析
刚看到这个问题,肯定有点懵,因为假如有相同的就加1的话,加1之后还可能与其它的数相同,继续加,依然有可能在哪个角落有一个数就重复了,所以,这样单纯的扫描数组,看起来可行型不大。
困扰我们的问题主要是什么呢?
就是,你不知道加完之后,哪个数会和这个数相同,要是我们能把相同的找出来就好了。
于是,思路来了,排序!!!
排序后,相同的肯定都在一起,如果加1,也可以根据下一个数来判断是否冲突,这样,这个麻烦的问题就解决了,然后,我们仔细思考一下具体思路:
排序后,如果A[i]==A[i-1]
,说明这里重复了,那么最简单的办法就是A[i]+1
。
如果A[i]<A[i-1]
呢?为什么,会出现这个情况呢,因为在前面相等的条件下,前面的数可能变大了,那么这个时候最好的办法还是A[i]=A[i-1]+1
,操作数就是A[i-1]-A[i]+1
。
为什么我们要说最简单的方法就是保持后一个比前一个大呢?
因为对于一个数组来说,全部不重复的理想条件就是后一个刚好比前一个大1,我们的目的就是创造这个理想条件。
注意:
- 其实源数组的值其实是在不断的被改变的,这样,我们就可以保证不重复了。
- 不要轻易的去排序,排序的目的一定是排完序后,可以更加方便的解决问题,不然反而会造成时间的浪费。
- 默认是升序,C++底层实现是插入排序和快速排序搭配使用。
0x03.解决代码–排序后解决
class Solution {
public:
int minIncrementForUnique(vector<int>& A) {
int ans=0;
sort(A.begin(),A.end());
for(int i=1;i<A.size();i++){
if(A[i]<=A[i-1]){
ans+=A[i-1]-A[i]+1;
A[i]=A[i-1]+1;
}
}
return ans;
}
};
ATFWUS --Writing By 2020–03–22