目录
学习到的知识点:
1. 数组长度为 奇数 2n+1 则中位数两边各有n个数 设左边所有数和中位数的差值和为x 右边所有数和中位数的差值和为y 则所有需要移动的次数为x+y;如果不选择中位数 例如选择中位数-1 这样总的移动次数 >= ((x-n) + (y+n) + 1);也即 最好的情况下比中位数大1 。
2. 如果数组长度是偶数 有两个中位数 选择两个中位数的任何一个或者两个中位数的平均数 都是可以的
3. 另外就是求移动次数的时候,除了使用逐个遍历的方式,还可以使用双指针从两头作差求和
方法一、排序 + 遍历
class Solution {
public int minMoves2(int[] nums) {
Arrays.sort(nums);
int n = nums.length;
if(n % 2 == 1){ //奇数个元素,中位数唯一
int target1 = nums[(n - 1) / 2];
int count1 = 0;
for(int num : nums){
if(num - target1 < 0){
count1 += target1 - num;
}else{
count1 += num - target1;
}
}
return count1;
}else{ //偶数个元素,中位数有两个,两个结果一致,去其中一个即可
int target2 = nums[(n - 1) / 2];
int count2 = 0;
for(int num : nums){
if(num - target2 < 0){
count2 += target2 - num;
}else{
count2 += num - target2;
}
}
// int target3 = nums[n / 2];
// int count3 = 0;
// for(int num : nums){
// if(num - target3 < 0){
// count3 += target3 - num;
// }else{
// count3 += num - target3;
// }
// }
//return Math.min(count1, count3);
return count2;
}
}
}
算法思路:
分奇数个元素和偶数个元素,偶数个元素时候可以返回任意一个中位数的结果。
复杂度分析:
时间复杂度O(nlogn) 排序
空间复杂度O(1)
方法二:排序 + 双指针
class Solution {
public int minMoves2(int[] nums) {
Arrays.sort(nums);
int i = 0,j = nums.length - 1, res = 0;
while (i < j) {
res += nums[j--] - nums[i++];
}
return res;
}
}
算法思路
不用区分奇数和偶数个元素,限制双指针 i < j 即可。右减左,然后同步移动指针。
复杂度分析:
时间复杂度O(nlogn) //排序
空间复杂度O(1)