leetcode-master/problems/kamacoder/好数组.md

1.1 KiB

算是贪心

整体思路是移动到中间位置(中位数),一定是 移动次数最小的。

有一个数可以不改变,对数组排序之后, 最小数 和 最大数 一定是移动次数最多的,所以分别保留最小 和 最大的不变。

中间可能有两个位置,所以要计算中间偏前 和 中间偏后的

代码如下:


#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;
}