问题描述
问题链接:https://leetcode.com/problems/minimum-moves-to-equal-array-elements-ii/#/description
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]
我的代码
开始的时候一直没想出来应该怎么做。看了讨论区的讨论,知道思路是先求中位数,然后求各个数到中位数的绝对值的和。
然后我发现并不会求中位数。于是默默地学习了快排和Quick Select,这才把代码写出来。
快排可参考:http://blog.csdn.net/mrbcy/article/details/65441835
QuickSelect可参考:http://blog.csdn.net/mrbcy/article/details/65442164
最后给出我的通过代码:
public class Solution {
public int minMoves2(int[] nums) {
/*
思路是算中位数。最后算每个数与中位数的差的绝对值。
*/
int len = nums.length;
int median = getMedian(nums);
int count = 0;
for(int i = 0; i < len; i++){
count += Math.abs(nums[i] - median);
}
return count;
}
private int getMedian(int[] nums){
return getKth(nums.length/2,nums, 0, nums.length - 1);
}
// 再默写一次Quick Select
private int getKth(int k, int[] nums ,int left, int right){
if(k == 0){
return nums[left];
}
return helper(nums, k, left, right);
}
private int helper(int[] nums, int k, int left, int right){
if(left == right){
// 只有1个数了,返回就是了
return nums[left];
}
// 来一趟快排
int i = left;
int j = right;
int key = nums[i];
while(i < j){
// 从后向前,找一个比key小的数
while(i < j && nums[j] >= key){
j--;
}
if(i < j && nums[j] < key){
nums[i] = nums[j]; // 不交换了,省时间
i++; // 填坑后移
}
// 从前向后,找一个比key大的数
while(i < j && nums[i] <= key){
i++;
}
if(i < j && nums[i] > key){
nums[j] = nums[i];
j--; // 同上
}
}
// 把key填入合适的位置
nums[i] = key;
// 递归
if(k < i && left < i){
return helper(nums, k ,left, i-1);
}
if(k > i && right > j){
return helper(nums, k, j+1, right);
}
return key;
}
}
打败了7.12%的Java代码。来看看讨论区
讨论区
Java(just like meeting point problem)
链接地址:https://discuss.leetcode.com/topic/68736/java-just-like-meeting-point-problem
这个是先调用了Java标准库的Arrays.sort()来排序的,居然打败了58%的Java代码。特别想看看标准库是怎么实现这个的。
代码如下:
public class Solution {
public int minMoves2(int[] nums) {
Arrays.sort(nums);
int i = 0, j = nums.length-1;
int count = 0;
while(i < j){
count += nums[j]-nums[i];
i++;
j--;
}
return count;
}
}
Java O(n) Time using QuickSelect
链接地址:https://discuss.leetcode.com/topic/68758/java-o-n-time-using-quickselect
这个代码明显也没比我快多少,思路一致。看来不是我代码写得不好,确实没有标准库快。估计人家没用递归。
找到了Arrays.sort()的源码解析。http://www.cnblogs.com/gw811/archive/2012/10/04/2711746.html人家用了这么多技术,快也是应该的。思路令人惊叹。