945 使陣列唯一的最小增量

2021-10-04 06:15:00 字數 2479 閱讀 8968

題目描述

解題思路

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 操作,陣列將變為...