題目描述
解題思路
1、先排序再遍歷:
先對陣列進行排序,自帶的排序就可以的。最小的元素肯定是不需要增量的,然後遍歷陣列比較大小,如果後乙個數字與前乙個相等,就把後面那個數字加一。這樣加一後會造成就是已經排好序的陣列,但是後面元素比前乙個小,所以判斷條件的時候要增加:如果a[i] <= a[i-1],那麼後乙個元素等於前乙個元素加一,不能直接加一,否則無法達到要求,會出現相鄰兩個數字相等。
public
intminincrementforunique
(int
a)}return move;
}
先排序再遍歷的方法,時間複雜度 o(nlogn)
結果:2、先計數再遍歷o(n)
第一種方法主要時間複雜度在於排序,也可以不進行排序,先計數再遍歷。因為題目裡面給了範圍限制,陣列長度小於40000且每個數字也小於40000,所以可以直接用陣列作為底層資料結構。在計數的時候得到max,可以減少後面的迴圈次數。
public
intminincrementforunique
(int
a)for(
int i =
0; i <= max ; i++)}
//最後max的那位要移動的次數應該是累乘得到的,例如最大值有5個,應該移動(1+2+3+4)=n*(n+1)/2次
// 最後, counter[max+1]裡可能會有從counter[max]後移過來的,counter[max+1]裡只留下1個,其它的d個後移。
d = count[max+1]
-1;
move += d*
(d+1)/
2;return move;
}
這種方法效果比前一種更好:
3、線性探測法o(n) (含路徑壓縮)這道題換句話說,就是需要把原陣列對映到乙個位址不衝突的區域,對映後的位址不小於原陣列對應的元素。
比如[3, 2, 1, 2, 1, 7]就對映成了[3, 2, 1, 4, 5, 7]。
我想了下,這道題目其實和解決hash衝突的線性探測法比較相似!
如果位址衝突了,會探測它的下乙個位置,如果下乙個位置還是衝突,繼續向後看,直到第乙個不衝突的位置為止。
關鍵點:因為直接線性探測可能會由於衝突導致反覆探測耗時太長,因此我們可以考慮探測的過程中進行路徑壓縮。
怎麼路徑壓縮呢?就是經過某條路徑最終探測到乙個空位置x後,將這條路徑上的值都變成空位置所在的下標x,那麼假如下次探測的點又是這條路徑上的點,則可以直接跳轉到這次探測到的空位置x,從x開始繼續探測。
下面用樣例2:[3, 2, 1, 2,1, 7],來模擬一遍線性探測的過程.
**實現:
這種方法提交的時候效率不太高,還不知道為什麼,題解裡面有用遞迴方式,**如下:
// 線性探測定址(含路徑壓縮)
private
intfindpos
(int a)
// 否則向後定址
// 因為pos[a]中標記了上次定址得到的空位,因此從pos[a]+1開始定址就行了(不需要從a+1開始)。
b =findpos
(b +1)
;
pos[a]
= b;
// 定址後的新空位要重新賦值給pos[a]哦,路徑壓縮就是體現在這裡。
return b;
}
945 使陣列唯一的最小增量
給定整數陣列 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 操作...
945 使陣列唯一的最小增量
計數 class solution else if taken 0 count x 0 return ans 線性探測法 路徑壓縮o n class solution return move 線性探測定址 含路徑壓縮 private intfindpos int a 否則向後定址 因為pos a 中...
Leetcode 945 使陣列唯一的最小增量
給定整數陣列 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 操作,陣列將變為...