題目描述
給定整數數組 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 操作是不能讓數組的每個值唯一的。
提示:
0 <= A.length <= 40000
0 <= A[i] < 40000
解題思路
先排序再遍歷數組
1. 首先將數組進行排序,然後從左到右遍歷數組。
2. 如果當前元素大於上一個元素,保持不變;如果當前元素小於等於上一個元素,就需要增加當前元素,直到大於上一個元素。
3. 時間複雜度:O(nlogn)
代碼
public int minIncrementForUnique(int[] A) {
Arrays.sort(A);
int count = 0;
for (int i = 1; i < A.length; i++) {
if (A[i] <= A[i-1]) {
count += A[i-1] - A[i] + 1;
A[i] = A[i-1] + 1;
}
}
return count;
}
代碼注意點
臨界值
1. 數組A = null:本題條件:0 <= A.length <= 40000,故A不可能為null, 可忽略。
2. A.length = 0 時代碼是否正常。
3. 操作次數為int類型是否會存在溢出問題:題目中條件“0 <= A[i] < 40000”,操作次數最大為(1+4000) * 4000 / 2,不會溢出。
邏輯細節
1. 計數與數組元素更改順序:一定要先根據A[i]和A[i-1]的值進行計數,再更改A[i]的值,否則A[i]的更改會使count計數錯誤。
2. 剛排序完成時,數組中前一個元素的值一定小於等於後一個元素的值,即A[i-1] <= A[i]。但是隨著不符合條件的存在,數組中元素的值在不斷的增長,可能會出現A[i-1] > A[i]的情況,故判斷條件應該為:A[i] <= A[i-1]。
其他解題思路
由於題目中“0 <= A[i] < 40000”, 數組中元素的取值範圍比較小,可以考慮使用計數的方法。
1. 例如輸入 [3, 2, 1, 2, 1, 7],計數之後有兩個 1 和兩個 2。我們先看最小的數,兩個 1 重複了,需要有一個增加到2,這樣 2 的數量變成了三個。在三個 2 中,又有兩個需要增加到 3,然後又出現了兩個 3…… 以此類推,可以計算出需要增加的次數。
2. 時間複雜度 O(n + k)。
題目來源
LeetCode: minimum-increment-to-make-array-unique (使數組唯一的最小增量)
閱讀更多 隨夢而飛的鶴 的文章