题目:
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]
题意:
给定一个非空整数数组,找到使所有数组元素相等所需的最小移动数,其中移动将所选元素递增1或将所选元素递减1。
代码:
public class Solution {
public int minMoves2(int[] nums) {
int n = nums.length;
if( n <= 1 ){
return 0;
}
else {
Arrays.sort(nums); //对数组排序
int mean = nums[n/2]; //找出中位数,中位数即为数组中下标在中间的数
int i;
int res = 0; //记录移动步数
for( i = 0; i < n; i++){
res += Math.abs(nums[i]-mean); //数组个数字减去中位数,即得移动步数
}
return res;
}
}
}
笔记:
1、刚开始本人计算整个数组的平均数,然后用每个数减去平均数,相加求和,得到最后的移动步数。提交后提示答案不对,网上参考了答案,要找中位数,仔细分析了下,发现出错原因如下:这个题的关键是找一个数,竖立一个靶子,然后所有的数都往这个靶子靠近。
如果数组个数是偶数,那么用这种方法计算是没有问题的,因为这时数组的中位数位置在两个数中间,平均数也在这两个数中间,因此无论这个中间数是取中位数的上下区间的数,或者取平均数,移动的步数都相等;
但如果数组个数是奇数,这时中位数位置是确定的。这时中位数两边的数个数相等,无论他们往哪个数字上移动,最后的移动步数都是相等的,即中位数两边的数移动的步数是确定的;因此,次数总的移动步数,就看中位数的移动了。如果都往中位数上移,那中位数移动步数为0,其他数字移动步数确定,总的移动步数就是最小的。
这个题找中位数的数学证明如下:
先将数组按递增的顺序排好序,y1:移动到数组第k个下标的移动步数 y2:移动到数组的中间(移动到数组中位数)的移动步数
y1y1
同理,当 ak<an2 时,也比 y2 大。
因此,如果取得不是中位数,最后的结果都会比这大。
参考:y1http://blog.youkuaiyun.com/liuchenjane/article/details/53244689