題目要求
Given a non-empty integer array, find the minimum number of moves required to make all array elements equal, where a move is incrementing a selected element by 1 or decrementing a selected element by 1.
You may assume the array's length is at most 10,000.
Example:
Input:
[1,2,3]
Output:
2
Explanation:
Only two moves are needed (remember each move increments or decrements one element):
[1,2,3] => [2,2,3] => [2,2,2]
問最少需要多少次操作,能夠將數組中所有元素的值修改爲一樣的(操作是指將數組中的元素加一或者減一)
思路和代碼
其實這題就是找到數組的中位數,該中位數就是最終修改成的元素。當然了,這裏的中位數不是廣義上的中位數,當數組的元素爲奇數時,“中位數”是從小到大排列後位於中間的數。如果是偶數的話,“中位數”是兩個中間的數之間的任意一個數字。
這裏很多人會以爲是計算出平均值作爲最終元素,其實不然。簡單的講一下爲何“中位數”是最終元素的原因。假設有一個長度爲n的數組,其中包括元素a1, a2, ... an
,已知該數組已經有序,則可以知道,對於任意一個數字M,它到各個元素的距離和dist爲|a[1] - M| + |a[2] - M| + ... + |a[n] - M|
。如果M<a1, 則dist = n * M - sum
, 同理,如果M > a1, 則dist = sum - n * M
。 簡單來說,如果M小於最小值或是大於最大值,每個元素都必須走到最小值或最大值之外才能到達M,因此M一定位於[a1, an]之間。
現在開始找M的最佳位置。將M從最小值a1逐步向最大值an移動。假設M=a1+1且M<a2, 此時可以確信的是a1的移動距離增加了1,但是同時an的移動距離減少了1。也就是說,如果M在ai和aj間移動,二者到M的距離和是不變的。但是對於a2,a3...,a[n-1]來說,每個元素的移動距離都減少了1。也就是說,C在不斷的向中位數移動的時候,對於整體數組的移動距離和來說是不斷減少的。同理,當C到達中位數,並且繼續向右移動時,會發現整體數組的移動距離也隨之增加。
代碼如下:
public int minMoves2(int[] nums) {
Arrays.sort(nums);
int i = 0, j = nums.length - 1, result = 0;
while(i < j) {
result += nums[j--] - nums[i++];
}
return result;
}