練習題】使數組唯一的最小增量

題目描述

給定整數數組 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 (使數組唯一的最小增量)


分享到:


相關文章: