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