462. Minimum Moves to Equal Array Elements II
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]
官方题解:https://leetcode.com/problems/minimum-moves-to-equal-array-elements-ii/solution/ (给了7种解法,真的有必要吗,显然是median)
grandyang: http://www.cnblogs.com/grandyang/p/6089060.html
方法1:
思路:
和Best Meeting Point这道题related。那么各个方法的区别就在于如何找到这个median。首先当然可以用quick select,问题是非常慢。
Complexity
Time complexity : Average Case: O(n). Quick-Select average case time complexity is O(n). Worst Case: O(n^ 2). In worst case quick-select can go upto n^2.
Space complexity : O(1). No extra space required.
class Solution {
public:
int minMoves2(vector<int>& nums) {
int n = nums.size();
int median = 0;
if (n % 2 == 0) {
median = (findKth(nums, n / 2) + findKth(nums, n / 2 - 1)) / 2;
}
else {
median = findKth(nums, n / 2);
}
int moves = 0;
for (int num: nums){
moves += abs(num - median);
}
return moves;
}
int findKth(vector<int> & nums, int k){
int pos = - 1, start = 0, end = nums.size() - 1;
while (start <= end){
pos = partition(nums, start, end);
if (pos == k) return nums[pos];
else if (pos < k) start = pos + 1;
else end = pos - 1;
}
return -1;
}
int partition(vector<int> & nums, int start, int end){
int pivot = nums[start], left = start + 1, right = end;
while (left <= right){
if (nums[left] < pivot && nums[right] >= pivot) {
swap(nums[left++], nums[right--]);
}
if (nums[left] >= pivot) left ++;
if (nums[right] < pivot) right--;
}
swap(nums[start], nums[right]);
return right;
}
};
方法2: sort + median
思路:
排序,直接定位median。注意这里都不用区分奇偶,因为最后我们要取的也要做一次取整,如果是偶数直接取右中位。
Complexity
Time complexity : O(nlogn). Sorting will take O(nlogn) time.
Space complexity : O(1). No extra space required.
class Solution {
public:
int minMoves2(vector<int>& nums) {
sort(nums.begin(), nums.end());
int res = 0, mid = nums[nums.size() / 2];
for (int num : nums) {
res += abs(num - mid);
}
return res;
}
};
方法3: without median
思路:
参见Best Meeting Point.
class Solution {
public:
int minMoves2(vector<int>& nums) {
int res = 0, i = 0, j = (int)nums.size() - 1;
sort(nums.begin(), nums.end());
while (i < j) {
res += nums[j--] - nums[i++];
}
return res;
}
};