2.2 KiB
2.2 KiB
149. 好数组
贪心思路:
整体思路是移动到中间位置(中位数),一定是 移动次数最小的。
有一个数可以不改变,对数组排序之后, 最小数 和 最大数 一定是移动次数最多的,所以分别保留最小 和 最大的不变。
中间可能有两个位置,所以要计算中间偏前 和 中间偏后的
代码如下:
#include<bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
vector<long> arr(n);
for (int i = 0; i < n; ++i) {
cin >> arr[i];
}
sort(arr.begin(), arr.end());
if (arr[0] == arr[n - 1]) {
cout << 1 << endl;
return 0;
}
long cnt = 0L;
long cnt1 = 0L;
// 如果要保留一个不改变,要不不改最小的,要不不改最大的。
// 取中间偏前的位置
long mid = arr[(n - 2) / 2];
// 不改最大的
for (int i = 0; i < n - 1; i++) {
cnt += abs(arr[i] - mid);
}
// 取中间偏后的位置
mid = arr[n / 2];
// 不改最小的
for (int i = 1; i < n; i++) {
cnt1 += abs(arr[i] - mid);
}
cout << min(cnt, cnt1) << endl;
return 0;
}
Java代码如下:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
long[] arr = new long[n];
for (int i = 0; i < n; ++i) {
arr[i] = scanner.nextLong();
}
Arrays.sort(arr);
if (arr[0] == arr[n - 1]) {
System.out.println(1);
return;
}
long cnt = 0L;
long cnt1 = 0L;
// 如果要保留一个不改变,要不不改最小的,要不不改最大的。
// 取中间偏前的位置
long mid = arr[(n - 2) / 2];
// 不改最大的
for (int i = 0; i < n - 1; i++) {
cnt += Math.abs(arr[i] - mid);
}
// 取中间偏后的位置
mid = arr[n / 2];
// 不改最小的
for (int i = 1; i < n; i++) {
cnt1 += Math.abs(arr[i] - mid);
}
System.out.println(Math.min(cnt, cnt1));
}
}